2012-02-20 5 views
4

Вот мой main.js перед использованием domReady:Как использовать domReady requireJS плагин правильно

require.config({ 
    paths : { 
     loader : 'libs/backbone/loader', 
     jQuery : 'libs/jquery/jquery-module', 
     Underscore : 'libs/underscore/underscore-module', 
     Backbone : 'libs/backbone/backbone-module', 
     templates : '../Templates' 
    } 
}); 

require([ 'app' ], function(app) { 
    app.initialize(); 
}); 

И app.js:

define([ 'jQuery', 'Underscore', 'Backbone', 'router', 
    'services/Initializers/MainFrameInitializer', 
    'services/Initializers/FlowsViewsInitializer', 
    'services/Initializers/EditModuleInitializer', 
    'services/Sandboxes/ModulesNavigationSandbox', 
    'services/Sandboxes/ApplicationStateSandbox', 'DataModel/Constants' ], 
    function($, _, Backbone, Router, MainFrameInitializer, 
     FlowsViewsInitializer, EditModuleInitializer, ModulesNavigationSandbox, 
     ApplicationStateSandbox, Constants) { 
     var initialize = function() { 
     // Pass in our Router module and call it's initialize function 
     MainFrameInitializer.initialize(); 
     FlowsViewsInitializer.initialize(); 
     EditModuleInitializer.initialize(); 
     ApplicationStateSandbox.startCheckStatus(); 
     ModulesNavigationSandbox.navigate(Constants.Modules.Home); 
     // Router.initialize(); 
     }; 

     return { 
     initialize : initialize 
     }; 
    }); 

Все работает хорошо, пока я не optimize проекта. Я выяснил, что сценарий начинает работать до того, как DOM готов, что было не так до оптимизации. Во всяком случае, я хочу использовать плагин domReady, чтобы сначала загрузить DOM.

Но, по-видимому, я понятия не имею, как это сделать правильно. Вот новая версия main.js:

require.config({ 
    paths : { 
     loader : 'libs/backbone/loader', 
     jQuery : 'libs/jquery/jquery-module', 
     Underscore : 'libs/underscore/underscore-module', 
     Backbone : 'libs/backbone/backbone-module', 
     templates : '../Templates' 
    } 
}); 

require([ 'domReady', 'app' ], function(domReady, app) { 
    domReady(app.initialize); 
}); 

Очень аккуратный и очень неправильно, потому что app загружается параллельно с domReady до DOM готова.

Как исправить это?

Спасибо.

EDIT

Я думаю, что я понял нашу проблему. Функции конструктора зависимостей app не должны запускать какой-либо зависимый от DOM код. Они должны просто возвращать функции, захватывая зависимую от DOM логику. Эта логика должна быть выполнена от app.initialize, которая гарантируется, когда DOM готов.

+0

Почему неправильно загружать «domReady» и «приложение» параллельно? Вы только на самом деле вызываете код из 'app', когда DOM готов. Или я неправильно понял? –

+0

Возможно, это я неправильно понял, как работает материал. Загрузка 'app' включает загрузку всех зависимостей приложений (и их довольно много), затем эти зависимости вызывается и результаты передаются в метод фабрики приложений, который возвращает само приложение. Если я правильно понимаю, зависимости 'app' выполняются параллельно с' domReady', что означает, что они могут запускаться до полной загрузки DOM. – mark

+0

Ничего * работает * если ваша фабричная функция, которую вы передаете 'define()', фактически запускает код. Обычно фабричная функция просто создает объект со способами, которые можно назвать * в какой-то момент в будущем * (вы это сделали). Поэтому, даже если вызов 'define()' будет запускать заводскую функцию, вы будете делать только приложение * real *, когда захотите. Как вы сделали, передав 'app.initialize' функцию' domReady'. Мне это кажется прекрасным. –

ответ

7

Может быть, я что-то не хватает, но не вы бы сделать вашу жизнь намного проще, выполнив:

require(['jQuery', 'app' ], function(jQuery, app) { 
    jQuery(function ($) { 
    app.initialize(); 
    }); 
}); 

в вашем main.js?

+0

Мы используем jQuery, но вы не можете использовать его прямо так, потому что jQuery не определяет себя как модуль в смысле requireJS. Сначала это требует определенных приготовлений, и мы делаем их. Также обратите внимание, что 'app' зависит от' jQuery', это его первая зависимость. – mark

+1

jQuery * есть * AMD совместимый с iirc 1.7. Вы всегда можете использовать загрузчик, если вы зависите от предыдущей версии. Ваше приложение и главное оба в зависимости от jQuery не будут нарушать что-либо (jquery все еще загружается один раз), но это позволит вам не добавлять еще один плагин. – ggozad

+0

ОК, но эта схема по-прежнему требует, чтобы фабричные методы модулей, от которых зависит 'приложение', не манипулируют DOM, потому что зависимости' app' разрешены и вызывается параллельно с загрузкой jQuery. Оригинальная проблема остается. Но мне кажется, что я понял, что здесь уловка - см. Редактирование моего сообщения. – mark

3

Если следовать документ по адресу: http://requirejs.org/docs/jquery.html, вам будет предложено внедрить требуется-JQuery библиотеку в голове документа:

<script data-main="main" src="libs/require-jquery.js"></script> 

Однако, если вы посмотрите на исходный код для примера, доступны на github, вы увидите, что «требует-jquery.js» генерируется простой конкатенации требует Lib файла и Jquery Lib файл:

cat require.js jquery.js > ../jquery-require-sample/webapp/scripts/require-jquery.js 

Это означает, что вы могли бы заменить скрипт встраивать в головной части со следующим скрипт внедряется в любом месте вашего документа (например, в самом низу его).

<script src="libs/require.js"></script> 
    <script src="libs/jquery-1.8.0.js"></script> 
    <script>require(["main"]);</script> 

Поскольку JQuery Lib определяет себя как модуль:

define("jquery", [], function() { return jQuery; }); 

Вы можете после этого использовать JQuery в качестве ссылки требуется в любом из вашего сценария. Например:

require(["jquery"], function($) { } 
7

Требуя приложение из внутри функции обратного вызова domReady, вы должны быть в состоянии требовать модуль domReady, а затем модуль приложения синхронно.

define(['require', 'domReady'], function(require, domReady) { 
    domReady(function() { 
    require(['app'], function(app) { 
     app.initialize(); 
    }); 
    }); 
});