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


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

我在DustJS上使用Backbone

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

<div id="parentView">
  <div class="section">
    {>"app/inc/responseMessage" /}
    <div class="userDetails">
      {! A button to get user details !}
    </div>
  </div>
</div>

这是我的部分 - responseMessage.dust

<div id="responseMessage">
  {@eq key="{data.success}" value="true"}
    <div class="alert alert-success success" role="alert">success</div>
  {/eq}
</div>

我的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
},

当事件发生时调用下面的函数,它执行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
}

我的回调函数的实现

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

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

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

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

我在这里想念的是什么?谢谢你的时间!


9201
2017-10-23 20:11


起源

你有意将新模型传递给 responseMessageView  或者你期望你在这段代码中提到的模型是相同的??你好像在做 this.model.set('data', response.data);  this.responseMessageView.model.set('data', response.data); 等等,看起来像一团糟...我们不知道是什么 事情 含有 initialize 在第一个代码块...我们不知道是什么 事情 包含第二个代码块..您可能想先解释这些视图,模型等之间的关系 - T J
@ t-j我编辑了这个问题。我不明白你的意思是什么? initialize()用于声明整个页面和部分视图。对不起,如果我无法解释自己。 - suprita shankar
通过 事情 我在问这是一个观点,收集等等......我没有得到你的意思“它只是在调用primaryViewSuccess时,然后responseViewSuccess没有采取最新的模型更改。“ 哪个视图没有采取哪种模式改变..?您有2个视图和2个模型。请基于此解释,谁应该根据谁更新。 - T J
我不明白的一件事是为两个视图分别建立模型的原因......他们似乎使用相同的数据 this.model.set('data', response.data);...如果你使用相同的型号,那么保持两个视图同步会更容易。此外,您不必手动设置 response.data 进入模型。你可以回来 response.data 从 parse 方法,它会自动设置。 - T J
告诉我你的POST回调是如何写的 - François Richard


答案:


你正在使用经典的Backbone render-with-subviews gotcha:当你渲染索引视图时,你正在替换它 所有 DOM节点这包括您的DOM节点 responseMessageView 实例与...相关联。如果你检查一下 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);
  }
});

在这里手动调用渲染时, 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);
  }
});

5
2017-10-26 18:22



这绝对有道理。但由于我使用的是DustJS,这对我不起作用:/ ..我这样做 this.$el.html(this.template(this.model.toJSON())); 父视图不显示最新的模型更改。 html不显示模型更改。 - suprita shankar


尝试使用成功回调,让我知道我认为你的问题可能来自这里:

this.model.save({att1:“value”},{success:handler1,error:handler2});

你还确定要使用listenToOnce吗?而不是listenTo ??


3
2017-10-25 10:28



不,这不起作用。我的功能看起来像这样 this.responseMessageView.model.save({data: {email: emailAddress.val()}}); ..而且我必须提到成功回调是肯定会被解雇的。因为我有控制台声明。 - suprita shankar
我试过这个 this.responseMessageView.model.save({data: {email: emailAddress.val()}}, {success :this.responseViewSuccess, error: this.responseViewError}); ..这不起作用:(我错过了什么? - suprita shankar
我听过但仍无济于事:/ - suprita shankar


试着做 this.delegateEvents() 渲染后(http://backbonejs.org/#View-delegateEvents)。


3
2017-10-26 18:13