javascript - شرح - تحميل مكتبة jquery




$(مستند).مُعادل حاليًا بدون jQuery (20)

لدي برنامج نصي يستخدم $(document).ready ، ولكنه لا يستخدم أي شيء آخر من jQuery. أود تفتيحه عن طريق إزالة تبعية jQuery.

كيف يمكنني تنفيذ بلدي $(document).ready وظيفة دون استخدام jQuery؟ وأنا أعلم أن استخدام window.onload لن يكون هو نفسه ، حيث يتم إطلاق window.onload بعد تحميل جميع الصور ، الإطارات ، إلخ.


أنا استخدم ببساطة:

setTimeout(function(){
    //reference/manipulate DOM here
});

وبخلاف document.addEventListener("DOMContentLoaded" //etc كما هو الحال في أعلى إجابة ، فإنه يعمل إلى حد بعيد مثل IE9 - http://caniuse.com/#search=DOMContentLoaded يشير فقط إلى IE11 مؤخرًا.

على سبيل المثال ، انتقل إلى https://netrenderer.com/index.php ، اختر Internet Explorer 9 من القائمة المنسدلة ، وأدخل https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html وانقر على "Render" ، https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html شيئًا أقرب إلى لقطة الشاشة في أسفل هذه المشاركة.

راجع شفرة جافاسكريبت التالية التي أستخدمها في العنوان للتلاعب بنمط "مخترق" Jekyll "" حسب رغبتي - بشكل خاص يمكنك الرجوع إلى كتلة if (location.pathname !== rootPath) لترى كيف أقوم بإدخال الارتباطات Blog Home والموقع الإلكتروني ، والتي يتم عرضها بواسطة IE9 لكل موقع NetRenderer.

من المثير للاهتمام أنا تعثرت على هذا الحل setTimeout في عام 2009: هو التحقق من استعداد overkill DOM؟ ، التي ربما كان من الممكن صياغة الكلمات بشكل أفضل ، حيث كنت أعني باستخدام أساليب أكثر تعقيدًا في أطر العمل.

setTimeout(function() {//delay execution until after dom is parsed
    var containerEls = document.getElementsByClassName('container');
    var headingEl = containerEls[0].getElementsByTagName('h1')[0];
    var headerEl = document.getElementsByTagName('header')[0];
    var downloadsSectionEl = document.getElementById('downloads');
    var rootPath = "/";
    var blogRootPath = "/blog/";

    containerEls[0].style.maxWidth = '800px';
    containerEls[1].style.maxWidth = '800px';
    headingEl.style.margin = '0';
    headerEl.style.marginBottom = '7px';
    downloadsSectionEl.style.margin = '0';

    if (location.pathname !== rootPath) {
        downloadsSectionEl.appendChild(generateNavLink('Home', rootPath));
        if (location.pathname !== blogRootPath) {
            downloadsSectionEl.appendChild(document.createTextNode(' | '));
            downloadsSectionEl.appendChild(generateNavLink('Blog Home', blogRootPath));
        }
    }

    function generateNavLink(linkText, hrefPath) {
        var navLink = document.createElement('a');
        var linkTextNode = document.createTextNode(linkText);
        navLink.setAttribute('href', hrefPath);
        navLink.appendChild(linkTextNode);
        return navLink;
    }
});


إليك أصغر مقتطف شفرة لاختبار DOM جاهزًا يعمل على جميع المتصفحات (حتى IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

انظر هذا answer .


تصحيح:

هنا هو بديل عملي لل jQuery جاهزة

function ready(callback){
    // in case the document is already rendered
    if (document.readyState!='loading') callback();
    // modern browsers
    else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
    // IE <= 8
    else document.attachEvent('onreadystatechange', function(){
        if (document.readyState=='complete') callback();
    });
}

ready(function(){
    // do something
});

مأخوذة من https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

بما أن الإجابة المقبولة كانت بعيدة جداً عن الاكتمال ، قمت بتجميع وظيفة "جاهزة" مثل jQuery.ready() استناداً إلى مصدر jQuery 1.6.2:

var ready = (function(){

    var readyList,
        DOMContentLoaded,
        class2type = {};
        class2type["[object Boolean]"] = "boolean";
        class2type["[object Number]"] = "number";
        class2type["[object String]"] = "string";
        class2type["[object Function]"] = "function";
        class2type["[object Array]"] = "array";
        class2type["[object Date]"] = "date";
        class2type["[object RegExp]"] = "regexp";
        class2type["[object Object]"] = "object";

    var ReadyObj = {
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        readyWait: 1,
        // Hold (or release) the ready event
        holdReady: function( hold ) {
            if ( hold ) {
                ReadyObj.readyWait++;
            } else {
                ReadyObj.ready( true );
            }
        },
        // Handle when the DOM is ready
        ready: function( wait ) {
            // Either a released hold or an DOMready/load event and not yet ready
            if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                if ( !document.body ) {
                    return setTimeout( ReadyObj.ready, 1 );
                }

                // Remember that the DOM is ready
                ReadyObj.isReady = true;
                // If a normal DOM Ready event fired, decrement, and wait if need be
                if ( wait !== true && --ReadyObj.readyWait > 0 ) {
                    return;
                }
                // If there are functions bound, to execute
                readyList.resolveWith( document, [ ReadyObj ] );

                // Trigger any bound ready events
                //if ( ReadyObj.fn.trigger ) {
                //    ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
                //}
            }
        },
        bindReady: function() {
            if ( readyList ) {
                return;
            }
            readyList = ReadyObj._Deferred();

            // Catch cases where $(document).ready() is called after the
            // browser event has already occurred.
            if ( document.readyState === "complete" ) {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                return setTimeout( ReadyObj.ready, 1 );
            }

            // Mozilla, Opera and webkit nightlies currently support this event
            if ( document.addEventListener ) {
                // Use the handy event callback
                document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
                // A fallback to window.onload, that will always work
                window.addEventListener( "load", ReadyObj.ready, false );

            // If IE event model is used
            } else if ( document.attachEvent ) {
                // ensure firing before onload,
                // maybe late but safe also for iframes
                document.attachEvent( "onreadystatechange", DOMContentLoaded );

                // A fallback to window.onload, that will always work
                window.attachEvent( "onload", ReadyObj.ready );

                // If IE and not a frame
                // continually check to see if the document is ready
                var toplevel = false;

                try {
                    toplevel = window.frameElement == null;
                } catch(e) {}

                if ( document.documentElement.doScroll && toplevel ) {
                    doScrollCheck();
                }
            }
        },
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i < length; i++ ) {
                                elem = args[ i ];
                                type = ReadyObj.type( elem );
                                if ( type === "array" ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === "function" ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled && !fired && !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },
        type: function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ Object.prototype.toString.call(obj) ] || "object";
        }
    }
    // The DOM ready check for Internet Explorer
    function doScrollCheck() {
        if ( ReadyObj.isReady ) {
            return;
        }

        try {
            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            document.documentElement.doScroll("left");
        } catch(e) {
            setTimeout( doScrollCheck, 1 );
            return;
        }

        // and execute any waiting functions
        ReadyObj.ready();
    }
    // Cleanup functions for the document ready method
    if ( document.addEventListener ) {
        DOMContentLoaded = function() {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            ReadyObj.ready();
        };

    } else if ( document.attachEvent ) {
        DOMContentLoaded = function() {
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", DOMContentLoaded );
                ReadyObj.ready();
            }
        };
    }
    function ready( fn ) {
        // Attach the listeners
        ReadyObj.bindReady();

        var type = ReadyObj.type( fn );

        // Add the callback
        readyList.done( fn );//readyList is result of _Deferred()
    }
    return ready;
})();

كيف تستعمل:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

لست متأكداً من مدى فعالية هذا الكود ، ولكنه كان ناجحاً في اختباراتي السطحية. استغرق هذا بعض الوقت ، لذلك آمل أن تتمكن أنت والآخرين من الاستفادة منه.

ملاحظة: أقترح compiling .

أو يمكنك استخدام http://dustindiaz.com/smallest-domready-ever :

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

أو الوظيفة الأصلية إذا كنت تحتاج فقط إلى دعم المتصفحات الجديدة (على عكس jQuery ready ، لن يعمل هذا إذا أضفت هذا بعد تحميل الصفحة)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})

تقوم الوظيفة الجاهزة في jQuery بعدد من الأشياء. بصراحة ، لا أرى هذه النقطة لاستبدالها ما لم يكن لديك مخرجات صغيرة بشكل مثير للدهشة من موقع الويب الخاص بك. jQuery هي مكتبة صغيرة جدًا ، وتتعامل مع جميع أنواع المتصفحات عبر المتصفح التي ستحتاج إليها لاحقًا.

على أي حال ، هناك نقطة صغيرة في نشره هنا ، فقط افتح jQuery وانظر إلى طريقة bindReady .

It starts by calling either document.addEventListener("DOMContentLoaded") or document.attachEvent('onreadystatechange') depending on the event model, and goes on from there.


حقاً ، إذا كنت مهتماً بـ Internet Explorer 9+ فقط ، فإن هذا الكود سيكون كافياً لاستبدال jQuery.ready :

    document.addEventListener("DOMContentLoaded", callback);

إذا كنت قلقًا بشأن Internet Explorer 6 وبعض المتصفحات الغريبة والنادرة ، فسيعمل ذلك:

domReady: function (callback) {
    // Mozilla, Opera and WebKit
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        // If Internet Explorer, the event model is used
    } else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", function() {
            if (document.readyState === "complete" ) {
                callback();
            }
        });
        // A fallback to window.onload, that will always work
    } else {
        var oldOnload = window.onload;
        window.onload = function () {
            oldOnload && oldOnload();
            callback();
        }
    }
},

حل الرجل المسكين:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

عرض Fiddle

إضافة هذا واحد ، أفضل قليلا أعتقد ، نطاق الخاصة ، وغير العودية

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

عرض Fiddle


ضع <script>/*JavaScript code*/</script> قبل علامة الإغلاق </body> مباشرةً.

من المسلم به أن هذا قد لا يتناسب مع أغراض الجميع لأنه يتطلب تغيير ملف HTML بدلاً من مجرد القيام بشيء ما في ملف جافا سكريبت.


عبر المتصفح (المتصفحات القديمة أيضًا) وحلاً بسيطًا:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

عرض التنبيه في jsfiddle


كنت أستخدم هذا مؤخرًا لموقع محمول. هذه هي النسخة المبسطة لجون رزيغ من "تقنيات جافا سكريبت Pro". ذلك يعتمد على addEvent.

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();

لقد تم طرح هذا السؤال منذ فترة طويلة. بالنسبة لأي شخص يشاهد هذا السؤال ، يوجد الآن موقع يسمى "قد لا تحتاج إلى jquery" والذي ينهار - حسب مستوى دعم IE المطلوب - كل وظيفة jquery ويوفر بعض المكتبات البديلة الأصغر.

قد لا يحتاج برنامج نصي جاهز للوثيقة IE8 وفقًا لك إلى jquery

function ready(fn) {
    if (document.readyState != 'loading')
        fn();
    else if (document.addEventListener)
        document.addEventListener('DOMContentLoaded', fn);
    else
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading')
                fn();
        });
}

لن تعمل حلول setTimeout / setInterval المعروضة هنا إلا في ظروف محددة.

تظهر المشكلة بشكل خاص في إصدارات Internet Explorer القديمة حتى 8.

المتغيرات التي تؤثر على نجاح هذه الحلول setTimeout / setInterval هي:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

الأصلي (جافا سكريبت الأصلي) رمز حل هذه المشكلة المحددة هنا:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

هذا هو الرمز الذي أنشأ فريق jQuery تطبيقه.


ما عليك سوى إضافة هذا إلى أسفل صفحة HTML ...

<script>
    Your_Function();
</script>

نظرًا لأنه يتم تحليل مستندات HTML من أعلى لأسفل.


من الجيد دائمًا استخدام مكافئات جافا سكريبت مقارنة بـ jQuery. أحد الأسباب هو عدد أقل من المكتبات التي تعتمد عليها وهي أسرع بكثير من مكافئات jQuery.

مرجع واحد رائع لمكافئات jQuery هو http://youmightnotneedjquery.com/ .

فيما يتعلق بسؤالك ، أخذت الرمز أدناه من الرابط أعلاه :) التحذير فقط هو أنه يعمل فقط مع Internet Explorer 9+ والإصدارات الأحدث.

function ready(fn) {
    if (document.readyState != 'loading') {
        fn();
    }
    else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}

هناك استبدال قائم على المعايير ، DOMContentLoaded معتمد من قبل أكثر من 98٪ من المتصفحات ، وإن لم يكن IE8:

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

الوظيفة الأصلية jQuery أكثر تعقيدًا من مجرد window.onload ، كما هو موضح أدناه.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}

يجدر النظر في صخرة addEvent () الصلبة و http://www.braksator.com/how-to-make-your-own-jquery .

هنا هو رمز في حال انخفض الموقع

function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e"+type+fn] = fn;
        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
        obj.attachEvent( "on"+type, obj[type+fn] );
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on"+type] = obj["e"+type+fn];
    }
}

var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var i, item;
            for(i = listEvents.length - 1; i >= 0; i = i - 1){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();

// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});

Edit of the edit of @duskwuff to support Internet Explorer 8 too. The difference is a new call to the function test of the regex and the setTimeout with an anonymous function.

Also, I set the timeout to 99.

function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}

If you are loading jQuery near the bottom of BODY, but are having trouble with code that writes out jQuery(<func>) or jQuery(document).ready(<func>), check out jqShim on Github.

Rather than recreate its own document ready function, it simply holds onto the functions until jQuery is available then proceeds with jQuery as expected. The point of moving jQuery to the bottom of body is to speed up page load, and you can still accomplish it by inlining the jqShim.min.js in the head of your template.

I ended up writing this code to make moving all the scripts in WordPress to the footer, and just this shim code now sits directly in the header.


If you don't have to support very old browsers, here is a way to do it even when your external script is loaded with async attribute:

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});

This approach is the shortest way I can think of.

The solution based on the DOMContentLoaded event only works if the script is loaded before the document, whereas the lazy check suggested here ensures the code is executed always, even in scripts loaded dynamically later on, exactly as the JQuery's document ready.

This code is compatible with all browsers (including some legacy, down to IE6 and Safari for Windows).

(function ready() {
    if (!document.body) {setTimeout(ready, 50); return;}
    // Document is ready here
})();

This was a good https://.com/a/11810957/185565 poor man's solution. One comment considered a counter to bail out in case of emergency. This is my modification.

function doTheMagic(counter) {
  alert("It worked on " + counter);
}

// wait for document ready then call handler function
var checkLoad = function(counter) {
  counter++;
  if (document.readyState != "complete" && counter<1000) {
    var fn = function() { checkLoad(counter); };
    setTimeout(fn,10);
  } else doTheMagic(counter);
};
checkLoad(0);




jquery