Backbone局部视图无法渲染最新模型

sup*_*kar 11 javascript jquery backbone.js backbone-views

我对Backbone相对较新,我遇到了这个问题.

我正在使用Backbone和DustJS

我的模板看起来像这样 - index.dust

<div id="parentView">
  <div class="section">
    {>"app/inc/responseMessage" /}
    <div class="userDetails">
      {! A button to get user details !}
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

这是我的部分 - responseMessage.dust

<div id="responseMessage">
  {@eq key="{data.success}" value="true"}
    <div class="alert alert-success success" role="alert">success</div>
  {/eq}
</div>
Run Code Online (Sandbox Code Playgroud)

我的JS看起来像这样

initialize: function() {
    this.responseMessageView = this.responseMessageView ||
        new ResponseMessageView({
            model: new Backbone.Model()
        }); // View is for the partial
    this.model = this.model || new Backbone.Model(); //View for the whole page
},
Run Code Online (Sandbox Code Playgroud)

当事件发生时调用下面的函数,它执行POST并成功返回.

primaryViewEventTrigger: function(event){
  //Button click on `index.dust` triggers this event and does a POST event to the backend

  this.listenToOnce(this.model, 'sync', this.primaryViewSuccess);//this will render the whole view. 
  this.listenToOnce(this.model, 'error', this.primaryViewError);
  this.model.save({data: {x:'123'}});
}

responseViewEventTrigger: function(event){
  //Button click on `responseMessage.dust` triggers this event and does a POST event to the backend

  this.listenToOnce(this.responseMessageView.model, 'sync', this.responseViewSuccess);//it should only render the partial view - responseMessage.dust
  this.listenToOnce(this.responseMessageView.model, 'error', this.primaryViewError);
  this.responseMessageView.model.save({data: {x:'123'}});
}
primaryViewSuccess: function(model,response){
    this.model.set('data', response.data);
    this.render();
}
responseViewSuccess: function(model,response){
    this.responseMessageView.model.set('data', response.data);
    console.log(this.responseMessageView.model);
    this.responseMessageView.render(); // Does not work in some cases
}
Run Code Online (Sandbox Code Playgroud)

我的回调函数的实现

exports.sendEmail = function sendEmail(req, res){
  req.model.data.success = true;
  responseRender.handleResponse(null, req, res);
};
Run Code Online (Sandbox Code Playgroud)

this.model属于整个页面的模型.然而this.responseMessageView.model是部分模型.

问题:在大多数情况下,这种方法完全正常.有一种情况是它不会使用最新的模型值渲染部分.当我点击按钮index.dustprimaryViewSuccess执行时.之后我点击另一个按钮并触发responseViewEventTrigger.它成功完成了POST,并将其responseViewSuccess存储在模型中.但它没有在前端显示出来.data.success仍然不是真的,而console.log(this.responseMessageView.model)表明attributes->data->success = true

但是当我刷新页面时它的行为完全相同.只是当它primaryViewSuccess被调用然后responseViewSuccess它没有采取最新的模型更改.换句话说,模型正在更新,但DOM保持不变.

我在这里错过了什么?谢谢你的时间!

Jus*_*tin 5

您正在使用经典的Backbone render-with-subviews gotcha:当您渲染索引视图时,您将替换所有 DOM节点.这包括您的responseMessageView实例所绑定的DOM节点.如果您检查responseMessageView.el它实际上会看到它已使用新模型数据更新,但该元素不再附加到索引的DOM树.

var Parent = Backbone.View.extend({
  template: _.template(''),
  render: function() {
    this.$el.html(this.template());
  },

  initialize: function() {
    this.render();
    this.child = new Child();
    this.$el.append(child.el);
  }
});
Run Code Online (Sandbox Code Playgroud)

在这里手动调用渲染时,child.el将不再在 parent.el(您可以使用检查器进行检查).

这里最简单的解决方法是child.setElement在父渲染后使用新渲染的div#responseMessage元素进行调用.更好的解决方法是responseMessageView事先拆除元素,然后重新连接:

var Parent = Backbone.View.extend({
  render: function() {
    this.responseMessageView.$el.detach();
    this.$el.html(this.template(this.model.toJSON()));
    this.$el.find('#responseMessage').replaceWith(this.responseMessageView.el);
  }
});
Run Code Online (Sandbox Code Playgroud)