骨干局部视图未渲染最新模型

Posted

技术标签:

【中文标题】骨干局部视图未渲染最新模型【英文标题】:Backbone partial view not rendering the latest model 【发布时间】:2016-01-23 11:31:27 【问题描述】:

我对 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-&gt;data-&gt;success = true

但是当我刷新页面时,同样的行为一切正常。只是当primaryViewSuccess 被调用然后responseViewSuccess 它没有接受最新的模型更改。 换句话说,模型正在更新,但 DOM 保持不变。

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

【问题讨论】:

您是有意将新模型传递给responseMessageView ,还是希望您在此代码中引用的模型相同..?您似乎在做this.model.set('data', response.data); this.responseMessageView.model.set('data', response.data); 等,看起来一团糟......我们不知道第一个代码块中包含initializething 是什么......我们不知道'不知道包含第二个代码块的 thing 是什么。你可能想先解释这些视图、模型等之间的关系 @t-j 我已经编辑了这个问题。我不明白你说的东西是什么意思? initialize() 用于声明整个页面和部分页面的视图。对不起,如果我不能很好地解释自己。 By thing 我在问它是否是视图、集合等...我没有明白你所说的“只是在调用 primaryViewSuccess 时然后 responseViewSuccess 它没有采用最新的模型更改。” 哪个视图没有采用哪个模型更改..?您有 2 个视图和 2 个模型。请在此基础上说明,谁应该根据谁更新。 我不明白的一件事是为两个视图使用不同模型的原因...它们似乎使用相同的数据this.model.set('data', response.data);...如果您使用相同的模型,那么它'将更容易保持两个视图同步。此外,您不必手动将response.data 设置为模型。你可以从parse方法返回response.data,它会被自动设置。 请告诉我您的 POST 回调是如何编写的 【参考方案1】:

您遇到了经典的 Backbone render-with-subviews 陷阱:当您渲染索引视图时,您正在替换 所有 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(可以使用inspector查看)。

这里最简单的解决方法是在父级使用新渲染的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 不显示模型更改。【参考方案2】:

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

this.model.save(att1: "value", success:handler1, error: handler2);

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

【讨论】:

不,这不起作用。我的函数看起来像这样this.responseMessageView.model.save(data: email: emailAddress.val()); ..另外我必须提到成功回调肯定会被触发。因为我有控制台语句。 我试过这个this.responseMessageView.model.save(data: email: emailAddress.val(), success :this.responseViewSuccess, error: this.responseViewError); ..这不起作用:(我错过了什么? 我听了但仍然无济于事:/【参考方案3】:

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

【讨论】:

以上是关于骨干局部视图未渲染最新模型的主要内容,如果未能解决你的问题,请参考以下文章

局部视图中的模型未返回任何数据

从局部视图访问父模型

MVC 在 EditorFor 中渲染局部视图

骨干无法读取骨干视图中未定义错误的属性“属性”

我可以在创建视图的模型中收听骨干视图的变化吗?

骨干路由器:等待首先获取数据