Как загрузить загрузочные модели в магистраль.js при использовании AMD (требуется.js)
костяк.документация js предлагает загружать загрузочные модели следующим образом:
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%= @accounts.to_json %>);
var Projects = new Backbone.Collection;
Projects.reset(<%= @projects.to_json(:collaborators => true) %>);
</script>
но это шаблон, который может быть использован в подход AMD (использование require.js)
единственное возможное решение-объявить глобальная переменная, хранящая данные JSON и использовать эту переменную позже в соответствующих initialize методы.
здесь лучше чтобы сделать это (без глобалов)?
9 ответов:
вот как мы загружаем данные таким образом, чтобы они не загрязняли глобальное пространство имен. Вместо этого он использует require.Яш исключительно. Это также поможет вам обеспечить начальную конфигурацию приложения на основе переменных в шаблоне.
в рамках вашей страницы
<script src="require.js"></script> <script> define('config', function() { return { bootstrappedAccounts: <%= @accounts.to_json %>, bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %> }; }); </script> <script src="app.js"></script>
globals.jsэтот файл проверяет конфигурацию и расширяет себя, используя любые возвращенные данные
define([ 'config', 'underscore' ], function(config) { var globals = { }; _.extend(globals, config); return globals; });
config.jsэтот файл нужен, если вы хотите быть возможность загрузки приложения независимо от того, если вы определили
configна странице.define(function() { // empty array for cases where `config` is not defined in-page return {}; });
app.jsrequire([ 'globals', 'underscore', 'backbone' ], function(globals) { if (globals.bootstrappedAccounts) { var accounts = new Backbone.Collection(globals.bootstrappedAccounts); } if (globals.bootstrappedProjects) { var projects = new Backbone.Collection(globals.bootstrappedProjects); } });
Похоже, вы можете использовать require.функция config () или глобальная функция "require" с опцией "config" для передачи данных в модуль через специальный модуль зависимостей. См.http://requirejs.org/docs/api.html#config-moduleconfig:
существует общая потребность передать информацию о конфигурации в модуль. Что информация о конфигурации обычно известна как часть приложения, и должен быть способ передать это в модуль. В RequireJS, это делается с помощью опции config для requirejs.конфигурация.)( Модули затем можно прочитать эту информацию, запросив специальный модуль " зависимость" и вызывая модуль.конфигурация.)(
Итак, для моделей начальной загрузки у нас есть, на HTML-странице верхнего уровня:
<script> var require = { config: { 'app': { bootstrappedAccounts: <%= @accounts.to_json %> bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %> } } }; </script> <script src="scripts/require.js"></script>затем в модуле приложения (app.js), у нас есть:
define(['module'], function (module) { var accounts = new Backbone.Collection( module.config().bootstrappedAccounts ); var bootstrappedProjects = new Backbone.Collection( module.config().bootstrappedProjects ); });здесь "модуль" - это специальная зависимость, поставляемая для этих типов случаев.
Это непроверено, но выглядит довольно конечно, из документации.
в RequireJS это делается с параметром config для
requirejs.config(). Затем модули могут прочитать эту информацию, запросив специальную зависимость "модуль" и вызвавmodule.config(). Пример:.HTML-код
<script> var require = { config: { 'app': { 'api_key': '0123456789-abc' } } }; </script> <script src="js/libs/require.js" data-main="js/main"></script>главная.js
require( ['app'], function(App) { new App(); });приложение.js
define( ['module'], function(module) { var App = function() { console.log( 'API Key:', module.config().api_key ); }; return App; });просто обратите внимание, что имя конфигурации-объект должно соответствовать имя модуля. В моем примере имя модуль был
app, поэтому имя объекта конфигурации должно быть названоappкак хорошо. В модуле вам нужно будет включить['module']как зависимость и называютmodule.config()[property name]для получения конфигурационных данных.прочитайте документацию об этом:http://requirejs.org/docs/api.html#config-moduleconfig
некоторые из ответов здесь приблизили меня к моей подобной проблеме, но ничего не прибило ее. В частности, самый ранжированный и принятый ответ дал, казалось, дал мне неприятное состояние гонки, где иногда фиктивный объект загружался первым. Это произошло в 100% случаев при использовании оптимизатора. Он также использует явные имена строк для модуля, который требует документации специально советует вам не делать.
вот как я это сделал. Как и храбрый Дэйв, я использую объект config для захвата параметров (в моем случае со страницы jsp), как так
<script type="text/javascript"> var require = { config: { options : { bootstrappedModels : ${models} } } } </script>в частности, обратите внимание, что мои параметры находятся в объекте, называемом options. это имя не является обязательным! хотя в документации об этом не упоминается, ниже показано, как require загрузит вашу конфигурацию (строка 564 в requirejs 2.1.1):
config: function () { return (config.config && config.config[mod.map.id]) || {}; },ключевым моментом является то, что должно быть свойство на объекте конфигурации с ключом mod.map.id который решает: "варианты".
отсюда вы можете теперь получить доступ к моделям, как так
define(['module'], function(module){ console.log(module.config().bootstrappedModels); //... });
вы можете добавить функцию loopy в конце вашего модуля AMD, чтобы проверить, когда определен метод init (чтобы его можно было заполнить после body или загрузить из include). таким образом, модуль гарантированно доступен, и инициализация может произойти, когда он будет готов.
require(...,function (...) { //define models collections, etc.. var initme = function () { if(document.initThisModule) document.initThisModule(); else setTimeout(initme, 10); }(); });
Я не (слишком) знаком с подходом AMD, но вместо использования глобальной переменной, почему бы вам не добавить JSON в dom.
например:
var json = ..., $jsonContainer = $(json).wrap("<script id='json-container' type='text/javascript'>").appendTo($("body"));затем вместо встроенного тега скрипта, как это предлагается в документации по магистрали, внутри документа ready:
$(function(){ MyCollection.reset($("#json-container").html()); ... });
как насчет того, чтобы сделать что-то вроде этого:
<script> define('Models', ['backbone'], function(Backbone) { var Models = { Accounts: new Backbone.Collection, Projects: new Backbone.Collection }; Models.Accounts.reset(<%= @accounts.to_json %>); Models.Projects.reset(<%= @projects.to_json(:collaborators => true) %>); return Models; }); </script>тогда Вы сможете использовать модели в других модулях, как это:
var models = require(['Models']); models.Accounts.doWhatYouNeed();или такой:
define(['any', 'dependencies', 'and', 'Models'], function(a, b, c, Models) { // Models will be available here });
Как описано выше, "модуль данных" (или config, или как вы хотите его назвать) может быть включен в файл, который уже сгенерирован в любом случае (например, индекс.HTML) но я думаю, что это довольно некрасиво.
другой способ-объявить его в своем собственном файле модуля, но для этого потребуется дополнительная поездка на сервер в производственных средах. Как только вы хотите построить и оптимизировать свои зависимости requirejs, модуль данных не может быть включен, потому что он динамически генерируется при загрузке страницы.
третьим вариантом может быть добавление его в один из файлов, которые вы обслуживаете (например, оптимизированный файл requirejs), но я понятия не имею, как/если это можно сделать.
Ansewr by @dlrust работает, но он не способен расширять param и передавать более чем из одного места в коде. Если вы попытаетесь сделать что-то подобное в своем шаблоне рендеринга:
<script> define('config', function() { return { bootstrappedAccounts: <%= @accounts.to_json %>, bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %> }; }); </script>и в другой файл добавить некоторые данные
<script> define('config', function() { return { goods: <%= some data %>, showcaseList: <%= some json or array %> }; }); </script>он был перезаписан (НЕ ПРОДЛЕВАТЬ!!!). В конфиге будут только последние объявленные данные.
мое решение: используется модель магистрали с set / get данные.
app.jsdefine("App", [], function() { window.App = { // модели Model: {}, // коллекции Collection: {}, // виды View: {}, // роутеры Router: {}, // модальные окна Modal: {}, // UI компоненты UI: {} }; return window.App; });
global.jsdefine(["App", "underscore", "backbone"], function(App, _, Backbone) { "use strict"; // модель глобальных данных App.Model.Global = Backbone.Model.extend({ defaults: {} }); return new App.Model.Global; });
index.php<!DOCTYPE html> <html> <head> <!--HEAD_START--> <script type="text/javascript" data-main="/app/init" src="/app/require/require.js"></script> <!--HEAD_END--> </head> <body> <div id="tm-inner-wrap"> <div id="loader"><i class="uk-icon-refresh uk-icon-spin"></i></div> <!--HEADER_START--> <?= $this->includeTpl('header_view'); ?> <!--HEADER_END--> <!--CONTENT_START--> <div>your html content data</div> <!--CONTENT_END--> <!--FOOTER_START--> <?= $this->includeTpl('footer_view');?> <!--FOOTER_END--> <script> require(["global"], function(Global) { Global.set("notifyList", <?=json_encode($this->notifyList);?>); }); </script> </div> </body> </html>другой шаблон
someTemplate.php<div class="tm-inner-body"> <div class="uk-container uk-container-center"> // content data </div> </div> <script> require(["global", "module/index"], function(Global) { Global.set("goodList", <?=json_encode($this->goodList);?>); }); </script>
index.jsrequire(["App", "core", "jquery", "uikit!uikit-addons-min", "underscore", "backbone", "global", "module/good/goodView"], function(App, Core, $, UIkit, _, Backbone, Global, goodView) { "use strict"; // Global.get("notifyList"); its too able App.Collection.Good = new Backbone.Collection(Global.get("showcaseList")["items"]); // вид списка товаров App.View.GoodList = Backbone.View.extend({ // елемент el: ".tm-good-list", // init initialize: function() { this.collection = App.Collection.Good; // список товаров this.drawList(); }, // отрисовка списка drawList: function() { this.$el.empty(); this.collection.each(function(item, index) { this.$el.append(this.drawItem(item)); }, this); }, // отрисовка елемента drawItem: function(data) { var good = new goodView({model: data}); return good.render().el; } }); App.View.Index = Backbone.View.extend({ el: "body", // пользовательские события events: { // }, // init initialize: function() { var $this = this; if(Global.get("showcaseList")) new App.View.GoodList(); } }); new App.View.Index(); });структура файла:

Comments