5

setTimeout 関数はいつも私に問題を引き起こすようです。現在、再帰的 (setTimeout を介して自分自身を呼び出す) で要素の高さを変更する関数があります。

この関数には、変更する要素とその要素の最大高さの 2 つの引数が送信されます。この関数の目的は、要素を展開すること、つまり一定のペースで「スライド ダウン」することです。おそらくjQueryでこの問題を解決できることは承知していますが、独自の機能を試しています。

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    {
        var factor = 10;
        var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
        element.style.height = new_height + 'px';

        var func_call = 'slide_down(' + element + ', ' + max_height + ');';
        window.setTimeout(func_call, 10);
    }
}

関数が最初に呼び出されたときに引数をテストしました。max_height は 20 に設定されています。これは、要素の目的の高さであるためです (.scrollHeight からこの値を取得しました)。

関数が完了したら、max_height が要素の高さになるまで関数を呼び出したいと思います。私はこの setTimeout 呼び出しでそれを行います:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);

そして、それは機能していません。これは機能します:

var func_call = 'alert(1);';
window.setTimeout(func_call, 10);

また、関数呼び出しを setTimeout ステートメントに直接入れようとしましたが、まだ機能しません。

要素の高さは最初の反復で変更されることに注意してください。関数は自分自身を呼び出すことはありません。したがって、要素変数は正しく設定されており、alert() を使用して、これも正しい max_height を表示しました。

alert(func_call);

これを警告します:

slide_down([object HTMLParagraphElement], 20);
4

6 に答える 6

19

これを行う場合:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';

要素を文字列に変換しているので、タイムアウトは次のようになります

slide_down("[Object]", 100);

これは明らかに機能しません。

あなたがしなければならないことは、クロージャーを作成することです - 少し複雑ですが、基本的には関数を作成し、古い関数のローカル変数は新しい関数内で引き続き使用できます。

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    {
        var factor = 10;
        var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
        element.style.height = new_height + 'px';

        var func = function()
        {
            slide_down(element, max_height);
        }

        window.setTimeout(func, 10);
    }
}

また、10 はタイムアウトとしては少し短いので、最低でも 50 を使用することをお勧めします。

于 2008-12-04T17:36:43.913 に答える
3

まず第一に、この「今、私は再帰的な関数を持っています(setTimeoutを介してそれ自体を呼び出します)」は、期間を変更していない場合、setIntervalを叫びます。

第 2 に、これは、element.toString() が "[object]" になるため、文字列 concat で要素参照が失われるためです。再検索できる ID を渡してみてください。参照を 1 レベル上に保存するか、(マット b が指摘したように) 展開されたメソッド フォームを使用してください。

于 2008-12-04T17:37:55.720 に答える
2

メソッドを書くためのより微妙な方法(Gregsの回答の拡張として):

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    { return; }

    var factor = 10,
        new_height = element.clientHeight + factor,
        f = arguments.callee;

    if( new_height > max_height )
    { new_height = max_height; }

    element.style.height = new_height + 'px';

    window.setTimeout(function() { f(element, max_height); }, 10);
}

このサンプルコードの本当の利点は、を使用することですarguments.callee。このようにして、名前を変更することにした場合でも、関数を壊すことはありません。また、new_height値の割り当ても単純化しました。古いコードの問題は、element.clientHeight + factor2回実行したことです。これは、ちょっと不必要です。この場合、パフォーマンスに顕著な影響があるわけではありません。ただし、同じことを何度も計算することは避け、後で使用するために結果を保存することをお勧めします。

于 2011-11-01T09:18:18.747 に答える
1

コードの問題は、要素パラメーターを渡せないことです。

それ以外の:

var func_call = 'slide_down(' + 要素 + ', ' + max_height + ');';

window.setTimeout(func_call, 10);

匿名関数を使用してみてください:

window.setTimeout(関数() {
    slide_down(要素, max_height)
}、10);

@matt.b: setTimeout 呼び出しに渡す引数 (あなたが行う方法) は、IE ではサポートされていません。

于 2008-12-04T17:40:44.763 に答える
1

私も似たような経験をしました。次回要素を渡すと、関数呼び出しで文字列に変換されるため、関数が実行されると、意図したものではなく、[object].string などの名前の要素を見つけようとします。

関数パラメーターを変更して要素の ID を取得し、関数内で最初に document.getElementById() 呼び出しを実行してみてください。

于 2008-12-04T17:34:29.907 に答える
0

2つのこと:

1.setTimeout()実行する文字列ではなく、関数とパラメーターを渡す別の呼び出し方法があります。実際、Gecko DOM のマニュアルには、お使いのバージョンの呼び出しsetTimeout()は推奨されないと記載されています。

それ以外の:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);

代わりにこれを試してください:

window.setTimeout(slide_down, 10, element, max_height);  

更新: RoBorg が述べたように、これは IE では機能しない可能性があるため、無視してもかまいません。


2.setTimeout()自分自身を呼び出した関数内からの呼び出しsetTimeout()は許可されていないか、うまく機能しないと感じています。コードを繰り返し実行したいので、このように呼び出しを連鎖させていると思いますか? もしそうなら、それwindow.setInterval()が目的です。

于 2008-12-04T17:34:37.067 に答える