How can I use yepnope.js with $(document).ready() effectively?

久未见 提交于 2019-11-28 17:48:57

问题


I have been implementing the yepnope script loader as part of the modernizr.js library. I have successfully got jQuery to load and jQuery dependent scripts afterwards. I am new to asynchronous loading of resources, so it's a bit new to me. I have been searching around, but haven't had much luck with the following.

My question is what are your opinions on how to effectively replace the functionality of $(document).ready() when working with the yepnope.js framework.

My theory was to create a appropriately named function in my base library and then set that variable on my pages to an anonymous function containing my existing $(document).ready() code. This variable would then be called by yepnope after all the scripts had loaded in the complete callback.

Would you agree that this is a good way of doing it, or am I approaching this entirely the wrong way?

(For those unaware, the asynchronous nature of yepnope.js means that the document calls $ or jQuery before the yepnope loader has finished, throwing a "$ is undefined" error <- please correct me if that is wrong.)

First question, hope it's a good one.


回答1:


If load jQuery without yepnope isn't a problem for you, there is a easier way to do.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<script>
    $.holdReady(true);

    yepnope.load({
        load: [
            'placeholder.js',
            'jquery-ui.min.js'
        ],
        complete: function (){
            $.holdReady(false);
        }
    });
</script>



回答2:


This is the technique I use. It allows me to sprinkle $(document).ready() style calls wherever I like. Using this method, you can take a site that already uses jQuery and has existing $(document).ready() calls, and easily retrofit yepnope.

First, add this line of JS, preferably in the document head, before any javascript that calls $(document).ready():

<script>
    var docready=[],$=function(o){function r(fn){docready.push(fn);}if(typeof o === 'function') r(o);return{ready: r}};
</script>

Then, have your yepnope jQuery test object set similar to this:

yepnope({
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',
    complete: function() {
        $ = jQuery;         
        for(n in docready) $(document).ready(docready[n]);
    }
});

We create a fake $(document).ready() before jQuery loads. This stores every $(document).ready() call in an array, docready. Then, once jQuery has loaded, we overwrite our temporary $ object with the now loaded real jQuery object. Then, we iterate through all the stored $(document).ready() calls, and execute them for real.

UPDATED: improved version from Chris Jones that also covers $(function() {}) style invocations.




回答3:


script tags are loading synchronously - so if you put your yepnope in a js file and load it via script tag:

   <script type="text/javascript" src="/my-yepnope-stuff.js"></script>
</body>

right before the closing body tag you can be quite sure to be at $(document).ready() state.

What you need to answer for yourself is whether it makes sense to force yepnope to load in a $(document).ready() fashion, as its main purpose is to break the synchronous loading order of script tags in the first place.




回答4:


Using guidance from @ezmilhouse, I thought about the best way to achieve what I was after while still keeping compatibility with our older code.

My solution was to set up my yepnope scriptloader to load all necessary scripts in a hierarchical fashion, based on their individual dependencies. Once all scripts are loaded, you can use the complete property of my call to yepnope to call my ready function. This meant that the document was effectively ready and the code would work with no issues.

I also moved my js to the base of my pages (something that I should have done a long time ago, but we had a lot of legacy pages! :) )

Here is an example (using false libray/script names for illustration purposes only):

yepnope({
    test: baseLib.debug,
    yep: { "max": "/version2/res/jquery/jquery-1.5.2.js" },
    nope: { "min": "/version2/res/jquery/jquery-1.5.2.min.js" },
    callback: {
        "max": function (url, result, key) {
            baseLib.Log("jQuery full loaded.");
        },
        "min": function (url, result, key) {
            baseLib.Log("jQuery min loaded.");
        }
    },
    complete: function () {
        if (window.$) {
            yepnope({
                test: base.debug,
                yep: {
                   "anotherscript": "script/url/here.js",
                   "anotherscript2": "script/url/here2.js"
                },
                nope: {
                    "anotherscript": "script/url/here-min.js",
                    "anotherscript2": "script/url/here2-min.js"
                },
                both: {
                    "anotherscript3": "script/url/here3.js"
                },
                callback: {
                    "anotherscript": function (url, result, key) {
                        baseLib.Log("anotherscript " + (result ? "Max" : "Min") + " loaded.");

                    },
                    "anotherscript2": function (url, result, key) {
                        baseLib.Log("anotherscript2 " + (result ? "Max" : "Min") + " loaded.");
                    },
                    "anotherscript3": function (url, result, key) {
                        baseLib.Log("anotherscript3 loaded.");
                    }
                },
                complete: function () {
                    baseLib.Log("Scripts Loaded");
                    baseLib.Page.Ready();
                }
            });

        }
        else {
            baseLib.Log("Could not load jQuery. No further jQuery dependent files loaded.", "error");
        }
    }
});

In my page js I will assign a function to baseLib.Page.Ready that will then be called by yepnope on complete.




回答5:


I think that Alex Sexton solution would be correct :

yepnope({
    load: '//ajax.googleapisOFFLINE.com/ajaxX/libs/jquery/1.7.1/jquery.min.js',
    callback: function () {
        if (!window.jQuery) {
            yepnope('/js/jquery-1.7.1.min.js');
        }
    },
    complete: function () {
      $(function(){
        $("div.whatever").css("color","red");
      });
    }
});


来源:https://stackoverflow.com/questions/5668311/how-can-i-use-yepnope-js-with-document-ready-effectively

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!