【问题标题】:How can I use yepnope.js with $(document).ready() effectively?如何有效地将 yepnope.js 与 $(document).ready() 一起使用?
【发布时间】:2011-04-14 19:03:14
【问题描述】:

我一直在将 yepnope 脚本加载器实现为modernizr.js 库的一部分。之后我成功地加载了 jQuery 和依赖于 jQuery 的脚本。我是异步加载资源的新手,所以对我来说有点新。我一直在四处寻找,但对以下内容的运气并不好。

我的问题是,您对在使用 yepnope.js 框架时如何有效地替换 $(document).ready() 的功能有何看法。

我的理论是在我的基础库中创建一个适当命名的函数,然后在我的页面上将该变量设置为包含我现有的 $(document).ready() 代码的匿名函数。在完成回调中加载所有脚本后,yepnope 将调用此变量。

您是否同意这是一种很好的方法,还是我完全错误地接近这个方法?

(对于那些不知道的人,yepnope.js 的异步特性意味着文档在 yepnope 加载程序完成之前调用 $ 或 jQuery,抛出“$ is undefined”错误

第一个问题,希望是个好问题。

【问题讨论】:

  • 澄清一下,我将它集成到一个站点中,其中包含许多适用于单个页面的现有 js 文件,这些文件依赖于 document.ready()。也许这是错误的做法——我想听听你的所有意见。

标签: javascript jquery document-ready yepnope asynchronous-loader


【解决方案1】:

如果在没有 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>

【讨论】:

  • 谢谢!我不知道 jQuery 有这个功能。更简单、更优雅的解决方案。
  • 我要不要放 $(document).ready();就在这下面?它需要在单独的&lt;script&gt; 标签中吗?
  • 你应该把$(document).ready()放在$.holdReady()下面单独的&lt;script&gt;标签中
【解决方案2】:

这是我使用的技术。它允许我在任何我喜欢的地方洒 $(document).ready() 风格的调用。使用此方法,您可以获取一个已经使用 jQuery 并具有现有 $(document).ready() 调用的站点,并轻松改造 yepnope。

首先,在任何调用 $(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>

然后,将您的 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]);
    }
});

我们在 jQuery 加载之前创建了一个假的 $(document).ready()。这会将每个 $(document).ready() 调用存储在一个数组中,doccready。然后,一旦 jQuery 加载完毕,我们用现在加载的真实 jQuery 对象覆盖我们的临时 $ 对象。然后,我们遍历所有存储的 $(document).ready() 调用,并真正执行它们。

更新:来自 Chris Jones 的改进版本,还涵盖了 $(function() {}) 样式调用。

【讨论】:

  • 嗨,我使用了你描述的方法并将 yepnope 放在结束 body 标记之前,一切正常。但是:我之前在某个地方加载了 jquery.min.js,所以使用这种方法会再次加载不必要的 jquery?问候安德里亚
  • 嗨 Andrea - 如果您已经尝试过预先加载 jQuery,您可以 1) 从 yepnope 中删除加载 jquery 的调用并保留其他脚本,2) 更改加载 jQuery 的 yepnope 块为此:{ test: typeof jQuery == 'undefined',是的:'//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',完成:function() { $ = jQuery; for(n in docready) $(document).ready(docready[n]); } } 3) 删除之前同步加载的 jQuery,并将任何使用 jQuery 的调用包装在 $(document).ready(function() { ... }) 块中。
  • 不错的解决方案。我也一定会尝试的。但是,在这种情况下,如何处理通过 JQuery.fn 或 $.fn 注册的 JQuery 插件呢?后者是我认为最糟糕的,因为这些注册会成功并在之后被覆盖;)......或者我在这里错过了一些关于插件使它们仍然像预期一样工作的观点?
【解决方案3】:

脚本标签是同步加载的——所以如果你把你的 yepnope 放在一个 js 文件中并通过脚本标签加载它:

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

在结束正文标记之前,您可以确定处于 $(document).ready() 状态。

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

【讨论】:

  • 我的问题是,在某些情况下,我必须测试文档准备好,因为我使用第三方控制库 (telerik)。如果找不到控件(即尚未加载),它们的函数将返回空值。除此之外,我想努力实现异步脚本加载。
【解决方案4】:

在@ezmilhouse 的指导下,我想到了实现我所追求的目标的最佳方式,同时仍保持与旧代码的兼容性。

我的解决方案是设置我的 yepnope 脚本加载器,以根据它们各自的依赖关系以分层方式加载所有必要的脚本。加载所有脚本后,您可以使用我对 yepnope 的调用的 complete 属性来调用我的就绪函数。这意味着文档已有效准备好,代码可以正常运行。

我还将我的 js 移到了页面的底部(我早就应该这样做了,但是我们有很多遗留页面!:))

这是一个示例(使用虚假库/脚本名称仅用于说明目的):

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

在我的页面 js 中,我将为 baseLib.Page.Ready 分配一个函数,然后 yepnope 将在完成时调用该函数。

【讨论】:

    【解决方案5】:

    我认为 Alex Sexton solution 是正确的:

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

    【讨论】:

      猜你喜欢
      • 2016-07-06
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多