Как эффективно использовать yepnope.js с $(document).ready()?

Я выполняю загрузчик скриптов yepnope как часть библиотеки modernizr.js. Я успешно получил jQuery для загрузки и jQuery-зависимые сценарии впоследствии. Я новичок в асинхронной загрузке ресурсов, так что это немного ново для меня. Я искал вокруг, но мне не повезло со следующим.

Мой вопрос: что вы думаете о том, как эффективно заменить функциональность $(document).ready() при работе с фреймворком yepnope.js?

Моя теория состояла в том, чтобы создать функцию с соответствующим именем в моей базовой библиотеке, а затем установить эту переменную на моих страницах в анонимную функцию, содержащую мой существующий код $(document).ready(). Эта переменная затем будет вызвана yepnope после того, как все сценарии были загружены в полный обратный вызов.

Согласитесь ли вы, что это хороший способ сделать это, или я подхожу к этому совершенно неправильно?

(Для тех, кто не знает, асинхронный характер yepnope.js означает, что документ вызывает $ или jQuery до того, как загрузчик yepnope завершил работу, выдавая ошибку "$ is undefined" <- исправьте меня, если это не так.)

Первый вопрос, надеюсь, он хороший.

5 ответов

Решение

Если загрузка jQuery без yepnope не является для вас проблемой, есть более простой способ сделать это.

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

Это техника, которую я использую. Это позволяет мне посылать вызовы в стиле $(document).ready() куда угодно. Используя этот метод, вы можете взять сайт, который уже использует jQuery и имеет существующие вызовы $(document).ready(), и легко модифицировать yepnope.

Во-первых, добавьте эту строку JS, предпочтительно в заголовок документа, перед любым JavaScript, который вызывает $(document).ready():

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

Мы создаем фальшивый $(document).ready() перед загрузкой jQuery. Это сохраняет каждый вызов $(document).ready() в массиве docready. Затем, после загрузки jQuery, мы перезаписываем наш временный объект $ теперь загруженным реальным объектом jQuery. Затем мы перебираем все сохраненные вызовы $(document).ready() и выполняем их по-настоящему.

ОБНОВЛЕНО: улучшенная версия от Криса Джонса, которая также охватывает вызовы стиля $(function() {}).

Теги скрипта загружаются синхронно - поэтому, если вы поместите свой yepnope в файл js и загрузите его через тег скрипта:

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

прямо перед закрывающим тегом body вы можете быть в состоянии $(document).ready().

Что вам нужно для себя ответить, так это то, имеет ли смысл принудительно загружать yepnope в виде $(document).ready(), поскольку его главная цель - в первую очередь нарушить порядок синхронной загрузки тегов скрипта.

Я думаю, что решение Алекса Секстона будет правильным:

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

Используя руководство @ezmilhouse, я подумал о том, как лучше всего достичь того, чего я достиг, при этом сохраняя совместимость с нашим старым кодом.

Мое решение состояло в том, чтобы настроить загрузчик сценариев yepnope для загрузки всех необходимых сценариев в иерархическом порядке, исходя из их индивидуальных зависимостей. После загрузки всех сценариев вы можете использовать complete свойство моего вызова в yepnope для вызова моей функции готовности. Это означало, что документ был фактически готов и код работал бы без проблем.

Я также переместил мои js в базу своих страниц (то, что я должен был сделать давным-давно, но у нас было много старых страниц!:))

Вот пример (использование ложных имен 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");
        }
    }
});

На моей странице JS я назначу функцию baseLib.Page.Ready это тогда будет вызвано yepnope по завершению.

Другие вопросы по тегам