programing

AMD (require.js)를 사용하는 동안 Backbone.js에서 부트 스트랩 된 모델을로드하는 방법

procenter 2021. 1. 17. 12:09
반응형

AMD (require.js)를 사용하는 동안 Backbone.js에서 부트 스트랩 된 모델을로드하는 방법


Backbone.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 데이터를 저장하는 전역 변수 를 선언 하고 나중에 관련 초기화 메서드에서이 변수를 사용하는 것입니다.

이를 수행 하는 더 좋은 방법 이 있습니까 (전역없이)?


이것이 글로벌 네임 스페이스를 오염시키지 않는 방식으로 데이터를 부트 스트랩하는 방법입니다. 대신 require.js를 독점적으로 사용합니다. 또한 템플릿 내의 변수를 기반으로 초기 앱 구성을 제공하는 데 도움이됩니다.

렌더링 된 페이지 내

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

require([
  '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 () 함수 또는 "config"옵션과 함께 "require"전역을 사용할 수 있습니다. http://requirejs.org/docs/api.html#config-moduleconfig 참조 :

구성 정보를 모듈에 전달해야하는 일반적인 필요성이 있습니다. 해당 구성 정보는 일반적으로 애플리케이션의 일부로 알려져 있으며이를 모듈로 전달할 방법이 필요합니다. RequireJS에서는 requirejs.config ()에 대한 config 옵션으로 수행됩니다. 모듈은 특별한 종속성 "모듈"을 요청하고 module.config ()를 호출하여 해당 정보를 읽을 수 있습니다.

따라서 부트 스트래핑 모델의 경우 최상위 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에서 이는 .NET 용 구성 옵션으로 수행됩니다 requirejs.config(). 그런 다음 모듈은 특수 종속성 "모듈"을 요청하고를 호출하여 해당 정보를 읽을 수 있습니다 module.config(). 예:

index.html

<script>
  var require = {
    config: {
      'app': {
        'api_key': '0123456789-abc'
      }
    }
  };
</script>
<script src="js/libs/require.js" data-main="js/main"></script>

main.js

require( ['app'], function(App) {
  new App();
});

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 % 발생했습니다. 또한 필수 문서에서 특별히 권장하지 않는 모듈에 대한 명시 적 문자열 이름을 사용합니다.

여기에 내가 일한 방법이 있습니다. Brave Dave와 유사하게 config 객체를 사용하여 매개 변수를 캡처합니다 (제 경우에는 jsp 페이지에서).

<script type="text/javascript">
    var require = {
        config: {
            options : { 
                bootstrappedModels : ${models}
            }
        }
    }
</script>

특히 내 매개 변수는 options라는 객체에 있습니다. 이 이름은 선택 사항이 아닙니다! 문서에는 이에 대한 언급이 없지만 다음은 require가 구성을로드하는 방법입니다 (requirejs 2.1.1의 564 행).

config: function () {
    return (config.config && config.config[mod.map.id]) || {};
},

요점은 'options'로 해석되는 mod.map.id 키가있는 구성 객체에 속성이 있어야한다는 것입니다.

여기에서 다음과 같은 모델에 액세스 할 수 있습니다.

define(['module'], function(module){
    console.log(module.config().bootstrappedModels);
    //...
});

AMD 모듈 끝에 루프 함수를 추가하여 init 메서드가 정의 된시기를 확인할 수 있습니다 (본문 뒤에 채우거나 포함에서로드 할 수 있도록). 그런 식으로 모듈의 사용이 보장되고 준비가되면 초기화가 발생할 수 있습니다.

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

그런 다음 백본 ​​문서에서 제안하는 포함 된 스크립트 태그 대신 문서 내부 준비 :

$(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
});

위에서 설명한 것처럼 '데이터 모듈'(또는 구성 또는 호출하려는 모든 항목)은 어쨌든 이미 생성 된 파일 (예 : index.html)에 포함될 수 있지만 이것은 다소 추한 것 같습니다.

또 다른 방법은 자체 모듈 파일에서 선언하는 것이지만 프로덕션 환경에서 서버에 대한 추가 왕복이 필요합니다. requirejs 종속성을 빌드하고 최적화하려는 즉시 페이지로드시 동적으로 생성되기 때문에 데이터 모듈을 포함 할 수 없습니다.

세 번째 옵션은 제공하는 파일 중 하나 (예 : 최적화 된 requirejs 파일)에 추가하는 것이지만, 어떻게 / 만약 할 수 있는지 모르겠습니다.


@dlrust의 Ansewr은 작동하지만 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>

덮어 썼습니다 (확장 되지 않음 !!! ). 구성에는 마지막으로 선언 된 데이터 만 있습니다.

내 솔루션 : 데이터 설정 / 가져 오기와 함께 백본 모델을 사용했습니다.

app.js

define("App", [], function() {
    window.App = {
        // модели
        Model: {},
        // коллекции
        Collection: {},
        // виды
        View: {},
        // роутеры
        Router: {},
        // модальные окна
        Modal: {},
        // UI компоненты
        UI: {}
    };
    return window.App;
});

global.js

define(["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.js

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

파일 구조 :

파일 구조

참조 URL : https://stackoverflow.com/questions/9916073/how-to-load-bootstrapped-models-in-backbone-js-while-using-amd-require-js

반응형