简体   繁体   English

如何有效地使用yepnope.js和$(document).ready()?

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

I have been implementing the yepnope script loader as part of the modernizr.js library. 我一直在实现yepnope脚本加载器作为modernizr.js库的一部分。 I have successfully got jQuery to load and jQuery dependent scripts afterwards. 之后我成功地加载了jQuery以加载jQuery依赖脚本。 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. 我的问题是,在使用yepnope.js框架时,您对如何有效替换$(document).ready()的功能有何看法?

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. 我的理论是在我的基础库中创建一个适当命名的函数,然后在我的页面上将该变量设置为包含我现有的$(document).ready()代码的匿名函数。 This variable would then be called by yepnope after all the scripts had loaded in the complete callback. 在所有脚本加载到完整回调之后,yepnope将调用此变量。

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.) (对于那些不知道的人,yepnope.js的异步性质意味着文档在yepnope加载器完成之前调用$或jQuery,抛出“$ is undefined”错误< - 如果错误请纠正我。)

First question, hope it's a good one. 第一个问题,希望它是一个好的。

This is the technique I use. 这是我使用的技术。 It allows me to sprinkle $(document).ready() style calls wherever I like. 它允许我在任何我喜欢的地方撒上$(document).ready()样式的调用。 Using this method, you can take a site that already uses jQuery and has existing $(document).ready() calls, and easily retrofit yepnope. 使用此方法,您可以使用已经使用jQuery并且已经存在$(document).ready()调用的站点,并轻松地改进yepnope。

First, add this line of JS, preferably in the document head, before any javascript that calls $(document).ready(): 首先,在任何调用$(document).ready()的javascript之前,最好在文档头中添加这行JS;

<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 jQuery测试对象设置类似于:

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. 我们在jQuery加载之前创建一个假的$(document).ready()。 This stores every $(document).ready() call in an array, docready. 这将每个$(document).ready()调用存储在一个数组docready中。 Then, once jQuery has loaded, we overwrite our temporary $ object with the now loaded real jQuery object. 然后,一旦jQuery加载,我们用现在加载的真实jQuery对象覆盖我们的临时$对象。 Then, we iterate through all the stored $(document).ready() calls, and execute them for real. 然后,我们遍历所有存储的$(document).ready()调用,并执行它们。

UPDATED: improved version from Chris Jones that also covers $(function() {}) style invocations. 更新:Chris Jones的改进版本,也涵盖了$(function(){})样式调用。

If load jQuery without yepnope isn't a problem for you, there is a easier way to do. 如果没有yepnope加载jQuery对你来说不是问题,那么有一种更简单的方法。

<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>

script tags are loading synchronously - so if you put your yepnope in a js file and load it via script tag: 脚本标签正在同步加载 - 所以如果你把你的yepnope放在一个js文件中并通过脚本标签加载它:

   <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. 在关闭正文标记之前,您可以确定处于$(document).ready()状态。

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. 您需要自己回答的是强制yepnope以$(document).ready()方式加载是否有意义,因为它的主要目的是首先打破脚本标记的同步加载顺序。

I think that Alex Sexton solution would be correct : 我认为Alex Sexton 解决方案是正确的:

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");
      });
    }
});

Using guidance from @ezmilhouse, I thought about the best way to achieve what I was after while still keeping compatibility with our older code. 使用@ezmilhouse的指导,我想到了实现我所追求的目标的最佳方法,同时仍然保持与旧代码的兼容性。

My solution was to set up my yepnope scriptloader to load all necessary scripts in a hierarchical fashion, based on their individual dependencies. 我的解决方案是设置我的yepnope脚本加载器,以基于各自的依赖关系以分层方式加载所有必需的脚本。 Once all scripts are loaded, you can use the complete property of my call to yepnope to call my ready function. 加载complete所有脚本后,您可以使用我对yepnope的调用的complete属性来调用我的ready函数。 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! :) ) 我也将我的js移动到我的页面底部(我应该在很久以前做过的事情,但我们有很多遗留页面!:))

Here is an example (using false libray/script names for illustration purposes only): 这是一个示例(使用false libray / script名称仅用于说明目的):

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. 在我的页面js中,我将为baseLib.Page.Ready分配一个函数,然后由yepnope在完成时调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM