سؤال

يبدو أن وظيفة setTimeout تمنحني دائمًا. في الوقت الحالي ، لدي وظيفة متكررة (تستدعي نفسها من خلال setTimeOut) وتغيير ارتفاع العناصر.

يتم إرسال الوظيفة وسيطتين: العنصر المراد تغييره وهذا الحد الأقصى للارتفاع. الغرض من الوظيفة هو تكشف العنصر ، أو "الانزلاق لأسفل" بوتيرة ثابتة. أنا أدرك أنه من المحتمل أن أحل هذه المشكلة مع 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);
هل كانت مفيدة؟

المحلول

عندما تفعل هذا:

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 كحد أدنى.

نصائح أخرى

بادئ ذي بدء ، هذا "الآن لدي وظيفة متكررة (يدعو نفسها من خلال settimeout)" صراخ " setInterval بالنسبة لي إذا لم تكن تختلف هذه الفترة.

ثانياً ، هذا لأن مرجع العنصر يتم فقدانه في سلسلة Concat as element.toString () سيكون [كائن]. حاول تمرير معرف يمكنك إعادة العثور عليه ، أو تخزين مستوى أعلى ، أو (كما رأيت للتو Matt B يشير إلى) نموذج الطريقة الموسعة.

طريقة أكثر دقة لكتابة الطريقة (كامتداد إلى إجابة 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 + factor مرتين ، وهو نوع نوعا ما. لا يكون له أي تأثير ملحوظ على أدائك في هذه الحالة. ولكن من الجيد دائمًا تجنب حساب نفس الأشياء مرارًا وتكرارًا ، ولكن فقط قم بتخزين النتيجة للاستخدام لاحقًا.

I had a similar experience. When you are passing element the next time through, it is getting converted to a string in the function call, so when the function runs, it tries to find an element named [object].string or something, instead of what you intended.

Try changing your function parameter to take the id of the element and do a document.getElementById() call first thing inside the function.

The problem with your code is that you are fail to pass element parameter.

Instead of:

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

window.setTimeout(func_call, 10);

try using anonymous function:

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

@matt.b: arguments passing into setTimeout call (the way you do) is not supported in IE.

Two things:

1. There is an alternate way to call setTimeout() in which you pass the function and parameters, rather than a string to execute. In fact, the Gecko DOM manual states that your version of calling setTimeout() is not recommended.

Instead of:

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

Try this instead:

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

Update: as RoBorg mentioned, this may not work in IE, so you might as well ignore it.


2. I have a feeling that calling setTimeout() from within a function that was called itself by setTimeout() is either not allowed or does not work well. I assume that you are chaining the calls like this because you want the code to execute repeatedly? If so, that is what window.setInterval() is for.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top