backbone.js 模型不触发事件

发布于 2024-12-18 12:50:20 字数 987 浏览 1 评论 0原文

我有一个视图似乎不想渲染,因为模型的更改事件没有触发。

这是我的模型:

var LanguagePanelModel = Backbone.Model.extend({
    name:       "langpanel",
    url:        "/setlocale",
    initialize: function(){
        console.log("langselect initing")
    }
})

这是我的视图:

var LanguagePanelView = Backbone.View.extend({
    tagName:        "div",
    className:      "langselect",
    render:         function(){
        this.el.innerHTML = this.model.get("content");
        console.log("render",this.model.get(0))
        return this;
    },
    initialize : function(options) {
        console.log("initializing",this.model)
        _.bindAll(this, "render");
        this.model.bind('change', this.render);
        this.model.fetch(this.model.url);
  }
});

这是我实例化它们的方式:

if(some stuff here)
{
   lsm = new LanguagePanelModel();
   lsv = new LanguagePanelView({model:lsm});
}

我获取了初​​始化的日志,但没有获取视图渲染的日志? 有什么想法吗?

I have a view which doesn't seem to want to render as the model's change event is not firing.

here's my model:

var LanguagePanelModel = Backbone.Model.extend({
    name:       "langpanel",
    url:        "/setlocale",
    initialize: function(){
        console.log("langselect initing")
    }
})

here's my view:

var LanguagePanelView = Backbone.View.extend({
    tagName:        "div",
    className:      "langselect",
    render:         function(){
        this.el.innerHTML = this.model.get("content");
        console.log("render",this.model.get(0))
        return this;
    },
    initialize : function(options) {
        console.log("initializing",this.model)
        _.bindAll(this, "render");
        this.model.bind('change', this.render);
        this.model.fetch(this.model.url);
  }
});

here's how I instantiate them:

if(some stuff here)
{
   lsm = new LanguagePanelModel();
   lsv = new LanguagePanelView({model:lsm});
}

I get logs for the init but not for the render of the view?
Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情深已缘浅 2024-12-25 12:50:21

我添加的问题已解决

var LanguagePanelModel = Backbone.Model.extend({
    //adding custom attributes to defaults (with default values)
    defaults: {
        name:       "langpanel",
        content:    "no content",
        rawdata:    "no data"
    },
    events:{
        //"refresh" : "parse"
    },
    url:        "/setlocale",
    initialize: function(){
        log("langselect initing");
        //this.fetch()
    },
    parse: function(response) {

        this.rawdata = response;
                // ... do some stuff
        this.trigger('change',this) //<-- this is what was necessary    
    }
})

The issue was resolved my adding

var LanguagePanelModel = Backbone.Model.extend({
    //adding custom attributes to defaults (with default values)
    defaults: {
        name:       "langpanel",
        content:    "no content",
        rawdata:    "no data"
    },
    events:{
        //"refresh" : "parse"
    },
    url:        "/setlocale",
    initialize: function(){
        log("langselect initing");
        //this.fetch()
    },
    parse: function(response) {

        this.rawdata = response;
                // ... do some stuff
        this.trigger('change',this) //<-- this is what was necessary    
    }
})
动听の歌 2024-12-25 12:50:21

与博士建议的不同,您不需要预定义属性。您需要将上下文传递给“bind” - this.model.bind('change', this.render, this);

请参阅 http://jsfiddle.net/7LzTt/ 或以下代码:

$(document).ready(function(){
    var LanguagePanelModel = Backbone.Model.extend({

        url:        "/setlocale",
        initialize: function(){
            console.log("langselect initing");
        }
    });

    var LanguagePanelView = Backbone.View.extend({
        el: $('#somediv'),

        initialize : function(options) {
            console.log("initializing",this.model);
            // _.bindAll(this, "render");
            //this.render();
            this.model.bind('change', this.render, this);
            //this.model.fetch(this.model.url);
        },

        render: function(){
            var c = this.model.get("content");
            alert(c);
            $(this.el).html(c);
            console.log("render",this.model.get(0));
            return this;
        }
    });

    var lpm = new LanguagePanelModel();
    var lpv = new LanguagePanelView({model:lpm});

    lpm.set({content:"hello"});    

}); //end ready

You don't need attributes to be predefined unlike PhD suggested. You need to pass the context to 'bind' - this.model.bind('change', this.render, this);

See working fiddle at http://jsfiddle.net/7LzTt/ or code below:

$(document).ready(function(){
    var LanguagePanelModel = Backbone.Model.extend({

        url:        "/setlocale",
        initialize: function(){
            console.log("langselect initing");
        }
    });

    var LanguagePanelView = Backbone.View.extend({
        el: $('#somediv'),

        initialize : function(options) {
            console.log("initializing",this.model);
            // _.bindAll(this, "render");
            //this.render();
            this.model.bind('change', this.render, this);
            //this.model.fetch(this.model.url);
        },

        render: function(){
            var c = this.model.get("content");
            alert(c);
            $(this.el).html(c);
            console.log("render",this.model.get(0));
            return this;
        }
    });

    var lpm = new LanguagePanelModel();
    var lpv = new LanguagePanelView({model:lpm});

    lpm.set({content:"hello"});    

}); //end ready
深居我梦 2024-12-25 12:50:20

我想这是关于设置模型的属性 - name 不是标准属性,并且您定义它的方式,它似乎可以通过使用 model.name 直接访问,而主干不允许那个据我所知。以下是有效的更改:) 您也可以看到相关的 fiddle :)

$(document).ready(function(){
var LanguagePanelModel = Backbone.Model.extend({
    //adding custom attributes to defaults (with default values)
    defaults: {
        name:       "langpanel",
        content: "Some test content"  //just 'cause there wasn't anything to fetch from the server
    },

    url:        "/setlocale",

    initialize: function(){
        console.log("langselect initing"); //does get logged
    }
});

var LanguagePanelView = Backbone.View.extend({
    el: $('#somediv'), //added here directly so that content can be seen in the actual div

    initialize : function(options) {
        console.log("initializing",this.model);
        _.bindAll(this, "render");
        this.render(); //calling directly since 'change' won't be triggered
        this.model.bind('change', this.render);
        //this.model.fetch(this.model.url);
    },

    render: function(){
        var c = this.model.get("content");
        alert(c);
        $(this.el).html(c); //for UI visibility
        console.log("render",this.model.get(0)); //does get logged :)
        return this;
    }
});

var lpm = new LanguagePanelModel();
var lpv = new LanguagePanelView({model:lpm});

}); //end ready

更新:

您不需要手动触发更改事件 - 将其视为不好的做法。这是主干文档的内容(注意:获取也会触发更改!)

获取

model.fetch([选项])
从服务器重置模型的状态。
如果模型从未填充过数据,或者您想要
确保您拥有最新的服务器状态。 “改变”事件
如果服务器的状态与当前状态不同将被触发
属性。接受选项哈希中的成功和错误回调,
其作为参数传递(模型、响应)。

因此,如果从服务器获取的值与默认值不同,则会触发更改事件,因此您无需自己执行此操作。如果您确实希望有这样的事件,那么您可以使用触发器方法,但自定义名称,因为它特定于您的应用程序。可以这么说,您基本上是在尝试使事件超载。完全没问题,但只是一个想法。

改变

model.change()
手动触发“change”事件。 如果你曾经
将 {silent: true}
传递给 set 函数以聚合快速
对模型进行更改时,您需要调用 model.change()
完成了。

仅当您通过将 silent:true 作为参数传递给模型的 set 方法来抑制事件时,才需要手动触发更改事件。

您可能还想查看主干文档中的“已更改”和其他事件。

编辑忘记为上面的示例添加更新的小提琴 - 你可以看到当通过显式调用 set 更改模型时,警报框会弹出两次 - 获取时也会发生同样的情况。因此,关于您“可能不需要”需要像您所做的那样手动触发“更改”这一事实的评论:)

I guess it's about setting the attributes of the model - name is not a standard attribute and the way you've defined it, it seems to be accessible directly by using model.name and backbone doesn't allow that AFAIK. Here are the changes that work :) You can see the associated fiddle with it too :)

$(document).ready(function(){
var LanguagePanelModel = Backbone.Model.extend({
    //adding custom attributes to defaults (with default values)
    defaults: {
        name:       "langpanel",
        content: "Some test content"  //just 'cause there wasn't anything to fetch from the server
    },

    url:        "/setlocale",

    initialize: function(){
        console.log("langselect initing"); //does get logged
    }
});

var LanguagePanelView = Backbone.View.extend({
    el: $('#somediv'), //added here directly so that content can be seen in the actual div

    initialize : function(options) {
        console.log("initializing",this.model);
        _.bindAll(this, "render");
        this.render(); //calling directly since 'change' won't be triggered
        this.model.bind('change', this.render);
        //this.model.fetch(this.model.url);
    },

    render: function(){
        var c = this.model.get("content");
        alert(c);
        $(this.el).html(c); //for UI visibility
        console.log("render",this.model.get(0)); //does get logged :)
        return this;
    }
});

var lpm = new LanguagePanelModel();
var lpv = new LanguagePanelView({model:lpm});

}); //end ready

UPDATE:

You don't need to manually trigger the change event - think of it as bad practice. Here's what the backbone documentation says (note: fetch also triggers change!)

Fetch

model.fetch([options])
Resets the model's state from the server.
Useful if the model has never been populated with data, or if you'd
like to ensure that you have the latest server state. A "change" event
will be triggered if the server's state differs from the current
attributes. Accepts success and error callbacks in the options hash,
which are passed (model, response) as arguments.

So, if the value fetched from the server is different from the defaults the change event will be fired so you needn't do it yourself. If you really wish to have such an event then you can use the trigger approach but custom name it since it's specific to your application. You are basically trying to overload the event so to speak. Totally fine, but just a thought.

Change

model.change()
Manually trigger the "change" event. If you've been
passing {silent: true}
to the set function in order to aggregate rapid
changes to a model, you'll want to call model.change() when you're all
finished.

The change event is to be manually triggered only if you've been suppressing the event by passing silent:true as an argument to the set method of the model.

You may also want to look at 'has changed' and other events from the backbone doc.

EDIT Forgot to add the updated fiddle for the above example - you can see that the alert box pops up twice when the model is changed by explicitly calling set - the same would happen on fetching too. And hence the comment on the fact that you "may not" need to trigger 'change' manually as you are doing :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文