backbone.js |後で検索のためにビューの要素を保存するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4542433

質問

これはBackBone.jsを使用する私の最初の試みであるため、メニュー項目を使用したレストランメニューをシミュレートする簡単なテストアプリケーションを作成することにしました。私は一緒にフォローしていました andyet.netからのこのクールなブログ投稿.

コレクションにモデルを追加するときに問題があります。ビューを更新するはずのコレクションの追加イベントにビューメソッドをバインドしました。これは、可能な限り無関係なコードを削除するコードを紹介します。

(注:ローカルスコープのようなものを削除しました var 簡潔にするための宣言と閉鎖。以下はまだ少し長く、私はそれが迷惑であることを知っていますが、それは非常に簡単で理解しやすいはずです):

MenuItem = Backbone.Model.extend({
    // initialize functions removed for brevity
});
Menu = Backbone.Model.extend({
    // initialize functions removed for brevity
    // MenuSelection property is defined here.
});
MenuSelection = Backbone.Collection.extend({ model: MenuItem });
MenuItemView = Backbone.View.extend({
    // render template
});

/**
 * This is unaltered from the code.  The error occurs here.
 */
RestaurantAppView = Backbone.View.extend({
    addMenuItem : function (MenuItem) {
        var view = new MenuItemView({ model : MenuItem });
        this.menuList.append(view.render().el);
        // ERROR occurs here.  error: "this.menuList is undefined"
    },
    initialize : function () {
        this.model.MenuSelection.bind('add', this.addMenuItem);
    },
    render : function () {
        $(this.el).html(ich.app(this.model.toJSON()));
        this.menuList = this.$('#menuList'); // IT IS DEFINED HERE
        return this;
    }
});

/**
 * Everything after this I left in just-in-case you need to see it.
 */
RestaurantAppController = {
    init : function (spec) {
        this.config = { connect : true };
        _.extend(this.config, spec);
        this.model = new Menu({
           name : this.config.name,
        });
        this.view = new RestaurantAppView({ model : this.model });
        return this;
    }
};
$(function() {
    // simulating ajax JSON response.
    var json = {
        Menu : {
            name : 'Appetizers',
            MenuItem : [
                {
                    name : 'toast',
                    description : 'very taosty',
                    price : '$20.00'
                },
                {
                    name : 'jam',
                    description : 'very jammy',
                    price : '$10.00'
                },
                {
                    name : 'butter',
                    description : 'very buttery',
                    price : '$26.00'
                }
            ]
        }
    };
    window.app = RestaurantAppController.init({
        name : json.Menu.name
    });
    $('body').append(app.view.render().el);
    app.model.MenuSelection.add(json.Menu.MenuItem);
});  

コメントで問題のある領域をマークしました。によると バックボーンドキュメント:

jQueryまたはZeptoがページに含まれている場合、各ビューには、ビューの要素内でスコープされたクエリを実行する$関数があります。

だから、私が設定している場合 this.menuList = this.$('#menuList'); レンダリング方法では、なぜアクセスできないのですか this.menuList の中に addMenuItem 方法?私が上部にリンクしたデモは、このように断言します。また、交換する場合 this.menuList jqueryセレクターの場合、そう

addMenuItem : function (MenuItem) {
    var view = new MenuItemView({ model : MenuItem });
    $('#menuList').append(view.render().el);
}

すべてが正常に機能します。しかし、私はしません 欲しいです 毎回Menulist IDを再選択します addMenuItem 実行されます。正しい道TM レンダリングされた後にキャッシュすることです。

また、注:私はおそらく、Icanhazテンプレートが十分に速く戻っていないことに問題があると思いましたが、その後 this.menuList 空の配列ではありません undefined, 、そうではありません。

役に立ちましたか?

解決

JavaScriptを使用して#1 Gotchaにぶつかります - 動的にスコープされています this キーワード。あなたがやってのけるとき this.addMenuItem それを拘束せずに参照として、 addMenuItem 関数はその概念を失います this. 。この行を置き換えるには、コードに修正する2つの簡単な方法があります。

this.model.MenuSelection.bind('add', this.addMenuItem);

これとともに:

this.model.MenuSelection.bind('add', _.bind(this.addMenuItem, this));

または、この行を初期化関数の上部に追加します。これは、同じことを効果的に達成します。

_.bindAll(this, 'addMenuItem');

他のヒント

おそらく、Renderメソッドが呼び出される前にAddMenuitemメソッドが呼び出されているため、Menulistの定義はAddMenuitemにありません。

押してみませんか this.menulist = this。$( '#menulist');初期化 方法と試してみますか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top