Javascript 如何在浏览器刷新后恢复backbonejs完整路由

Javascript 如何在浏览器刷新后恢复backbonejs完整路由,javascript,backbone.js,Javascript,Backbone.js,这是一个关于主干JS的架构问题: AppView包含加载了LeadsView的DOM元素占位符 LeadsView包含要显示的DOM占位符LeadsView 我当前的路线是#app/leads/1,这意味着所有3个视图都已加载。AppView->LeadsView->LeadsView 现在,用户突然按下了浏览器的刷新按钮。路由器将尝试将其传送到#app/leads/:1,路由到“app/leads/:lead\u id:“showLeadView”,但AppView和LeadsView这次未呈

这是一个关于主干JS的架构问题:

AppView
包含加载了
LeadsView
的DOM元素占位符
LeadsView
包含要显示的DOM占位符
LeadsView

我当前的路线是
#app/leads/1
,这意味着所有3个视图都已加载。
AppView
->
LeadsView
->
LeadsView

现在,用户突然按下了浏览器的刷新按钮。路由器将尝试将其传送到
#app/leads/:1
,路由到
“app/leads/:lead\u id:“showLeadView”
,但
AppView
LeadsView
这次未呈现,因此
LeadView
的呈现将失败

它正在寻找要将自身呈现到其中的DOM元素,但找不到它

如何用主干处理这个问题

蒂亚,
Nimrod。

当点击
“app/leads/:lead\u id:”showleadwiew“
路线时,您可以通过编程方式初始化和呈现其他视图

现在的问题是:如何查找视图是否已渲染

我通过向模型和集合中添加一个新属性来解决这个问题,该属性将告诉我它们是否已填充(如果已获取或已设置属性)。可以在中找到这方面的实现

看起来是这样的:

isPopulated: function() {
  /*jshint -W089 */

  // We are populated if we have attributes set
  var attributes = _.clone(this.attributes),
      defaults = getValue(this, 'defaults') || {};
  for (var default_key in defaults) {
    if (attributes[default_key] != defaults[default_key]) {
      return true;
    }
    delete attributes[default_key];
  }
  var keys = _.keys(attributes);
  return keys.length > 1 || (keys.length === 1 && keys[0] !== this.idAttribute);
}
if(!appModel.isPopulated())
    this.showAppView();

if(!leadsCollection.isPopulated())
    this.showLeadsView();
使用此方法,我可以验证渲染父视图所需的集合是否已填充。如果没有,则调用在导航到
app
然后导航到
leads
时将调用的方法(实际上,您可以通过编程方式访问路线)

它可能看起来像这样:

isPopulated: function() {
  /*jshint -W089 */

  // We are populated if we have attributes set
  var attributes = _.clone(this.attributes),
      defaults = getValue(this, 'defaults') || {};
  for (var default_key in defaults) {
    if (attributes[default_key] != defaults[default_key]) {
      return true;
    }
    delete attributes[default_key];
  }
  var keys = _.keys(attributes);
  return keys.length > 1 || (keys.length === 1 && keys[0] !== this.idAttribute);
}
if(!appModel.isPopulated())
    this.showAppView();

if(!leadsCollection.isPopulated())
    this.showLeadsView();
正如您所见,这意味着在路由器中保留对
appModel
leadsCollection
的引用

更新(澄清)
在我回答的第一行中,我提到了如下内容:

isPopulated: function() {
  /*jshint -W089 */

  // We are populated if we have attributes set
  var attributes = _.clone(this.attributes),
      defaults = getValue(this, 'defaults') || {};
  for (var default_key in defaults) {
    if (attributes[default_key] != defaults[default_key]) {
      return true;
    }
    delete attributes[default_key];
  }
  var keys = _.keys(attributes);
  return keys.length > 1 || (keys.length === 1 && keys[0] !== this.idAttribute);
}
if(!appModel.isPopulated())
    this.showAppView();

if(!leadsCollection.isPopulated())
    this.showLeadsView();
  • AppView
    引用了一个子视图
    LeadsView
    ,该子视图引用了一个子视图
    LeadsView
  • 在路由器中有一个
    AppView
    实例
  • 您将
    appModel
    传递给
    AppView
    并在点击
    app
    路由器时调用
    .render()
  • 您将
    leadsCollection
    传递给
    AppView.getLeadsView()
    并在点击
    leads
    路线时调用它的
    .render()
  • 将右侧的
    lead
    模型从
    leadsCollection
    传递到
    AppView.getLeadsView().getLeadsView()
    并在点击路线时对其调用
    .render()
或者您可以使用类似胸部的东西

它已经添加了对子视图的处理(负责事件委派、事件销毁、DOM清理等),并为其提供了模板处理程序,以便您可以在模板中指向要呈现子视图的位置


我希望现在我的意思更清楚了,正如你所看到的,它回答了你的问题。

你最初是如何表达所有这些观点的?显然不在路由处理程序中-这是您必须做的。你的路由器应该检查当前的路线,并决定如何相应地渲染视图。此外:“
AppView,其中包含加载了LeadsView的DOM元素占位符。LeadsView包含用于显示LeadView的DOM占位符”
“在您直接指定目标元素时读取,如
view.render();视图。$el.appendTo($(“#直接寻址元素”)
。考虑嵌套视图,然后将代码<代码>子视图.RelEd();子视图.el.appendTo(this.el);//其中,$el是当前视图
。你应该提供更多的视图代码和概述结构的路由器代码。谢谢@try catch最后你做对了,我没有呈现子视图,而是直接访问元素。好的捕获:-)我理解,但实际上我认为这不是正确的架构设计,事实上正如@try catch最后提到的,正确的方法是使用子视图,而不是直接访问这些视图上的dom元素。然而,我同意呈现和已经呈现的文档片段可能是多余的,为此,我们必须检查它是否还没有呈现。在我回答的第一行中,我提到的正是@try catch最后说的话。通过,您可以通过编程方式初始化和呈现其他视图(这意味着其他视图是子视图,您可以调用
.render()
方法。正如我在回答中所说,你真正的问题是找到它们是否已经被渲染。为什么你不认为使用在路线被击中时渲染的子视图是糟糕的架构?更新了我的回答并澄清了这一点。顺便说一句,你的问题是如何做,而不是什么是最好的方法。