Backbone部分视图没有呈现最新的模型。

11

我对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>

以下是我的部分代码 - responseMessage.dust

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

我的 JavaScript 代码长这个样子

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

但是当我刷新页面时,相同的行为都完美地工作。只是当将调用primaryViewSuccessresponseViewSuccess时,它没有采用最新的模型更改。换句话说,模型正在更新,但DOM保持不变。

我在这里缺少什么?感谢您的时间!


你是有意地把新模型传递给 responseMessageView,还是你希望在代码中引用的模型保持一致?你似乎在做 this.model.set('data', response.data);this.responseMessageView.model.set('data', response.data); 等操作,看起来有些混乱...我们不知道第一个代码块中的 东西 是什么...我们也不知道第二个代码块中的 东西 是什么...你可能需要首先解释一下这些视图、模型之间的关系 - T J
@t-j我已经编辑了这个问题。我不明白你说的“thing”是什么意思?initialize()用于声明整个页面和部分页面的视图。如果我表述不清,很抱歉。 - suprita shankar
我不理解的一件事是为什么视图需要单独的模型...它们似乎在使用相同的数据 this.model.set('data', response.data);...如果你使用相同的模型,那么保持两个视图同步会更容易。此外,您不必手动将 response.data 设置到模型中。您可以从 parse 方法返回 response.data,它将自动设置。 - T J
@TJ 回答第一个问题 - 发生了两个事件。其中一个应该触发 primaryViewSuccess,另一个是 responseViewSuccess。它们各自拥有自己的模型和视图需要更新。现在,如果我触发 responseViewSuccess,它可以完美地工作。但是当我先触发 primaryViewSuccess,然后再触发 responseViewSuccess 时,它就无法正常工作了。 - suprita shankar
但是你如何使用它并更新你的模型,这就是我需要的。 - François Richard
显示剩余6条评论
3个回答

5
你遇到了经典的Backbone渲染子视图陷阱:当你渲染索引视图时,你会替换所有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);
  }
});

在您手动调用 render 方法时,child.el 不再在其父元素 parent.el 中(您可以使用检查器进行检查)。
最简单的解决方法是,在父元素使用新渲染的 div#responseMessage 元素进行渲染后,调用 child.setElement。更好的解决方法是先分离 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);
  }
});

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

3
尝试使用成功回调并让我知道,我认为你的问题可能来自这里:
这个模型.save({att1 : "value"}, {success :handler1, error: handler2});
另外,你确定要使用listenToOnce而不是listenTo吗?

不行,这个不起作用。我的函数看起来像这样 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
我已经使用了listenTo,但仍然没有用 :/ - suprita shankar

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接