javascript - 不了解其容器的主干 View 、通过 AJAX 获取的模型、没有 UI/UX 权衡和可维护的代码

标签 javascript jquery backbone.js backbone-views

由于我不完全确定我的问题实际上在哪个级别上得到最好的解决,所以我想总结一下我所走的道路以及我首先尝试的事情:

这或多或少与 $el 有关(我认为)。

正如大多数基本 Backbone 示例所述,我首先在其 View 中定义 $el,例如

Invoice.InvoiceView = Backbone.View.extend({
  el: $('#container'),
  template: ..,
  ..
});

感觉不对, View 应该了解其父级(=容器)。 http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/上写的“将 View 与其他 DOM 元素分离”段落)完美地用语言表达了它。

按照本文的建议,我转而在调用 render() 方法时将 $el 传递给 View 。示例:

$('#container').html( new WineListView({model: app.wineList}).render().el );

到目前为止一切顺利 - 但现在 render() 被调用,虽然它可能不应该(还)被调用。

例如, View 在其initialize()例程中异步获取模型。添加到 resetsync 的绑定(bind)(例如 this.model.bind('sync', this.render, this))可确保,一旦获取模型,render() 肯定会被调用,但是如上所述,在尚未获取模型时,render() 仍然可能被调用

不太好,但是工作(TM),我通过检查模型的主键是否存在来解决这个问题:

render: function() {
  if(this.model.get('id')) {
    ...
}

但是,我没想到的是 - 如果它确实没有记录(至少我没有找到任何相关内容),我认为它确实应该是 - 获取操作似乎不是原子的。虽然主键(“id”)可能已经是模型的一部分,但其余部分可能还不是。因此不能保证模型完全以这种方式获取。但无论如何,整个检查似乎都是错误的,所以我做了一些研究,并得到了 deferred.done 回调,这听起来正是我正在寻找的,所以我的代码变成了这样:

render: render() {
  var self = this;
  this.model.deferred.done(function() {
    self.model.get('..')
  };
  return this;
}
..
$('#container').html( new WineListView({model: app.wineList}).render().el);

它有效!不错吧?呃……不是真的。从运行时流程的 Angular 来看,这可能很好,但该代码相当麻烦(温和地说......)。但我什至会咬紧牙关,如果没有那么小的细节,这段代码会立即设置(=替换) View ,但稍后填充它(由于延迟) .

假设您有两个(全页) View ,一个显示和一个编辑 - 并且您希望立即在这两个 View 之间切换(例如,在点击保存编辑 View 中,它会变成显示 View 。但是使用上面的代码它会立即设置(=重置) View 并且<一旦 deferred 触发(例如,一旦获取模型完成),strong>then 就会渲染其内容。 这可能是短暂的闪烁或较长的空白过渡页。不管怎样,都不酷。

所以,我想我的问题是:如何实现不知道其容器的 View ,涉及需要获取的模型,应按需渲染的 View (但仅在获取模型后完全),无需接受 UI/UX 权衡,并且 - 锦上添花 - 最终拥有可维护的代码。

最佳答案

首先,您发现的第一个方法很糟糕( View 构造函数中的硬编码选择器)

第二个:new WineListView({model: app.wineList}).render().el非常常见,也不错。这需要你从 render 方法返回对 view 的引用,而且每个人似乎都遵循这一点,这是不必要的。

最好的方法(imo)是简单地将 View 元素附加到容器,就像这样

$('#container').html(new WineListView({model: app.wineList}).el);

WineListView 不需要知道它将在哪里使用,并且无论初始化 WineListView 是什么,都不需要担心何时渲染 WineListView View 实例:

因为 el 是对 HTML 元素的实时引用,因此 View 实例可以随时修改它,并且更改将反射(reflect)在它附加的任何位置。 DOM/当它附加到 DOM 中时。

例如,

WineListView = Backbone.View.extend({
  initialize: function(){
     this.render(); // maybe call it here
     this.model.fetch({
       success: _.bind(this,function(){
         this.render(); // or maybe here 
       })
     });
  }
});
<小时/>

关于闪烁:这几乎与渲染或主干无关,只是您将一个元素替换为另一个元素,即使您的新 View 立即渲染,也会有一小段时间的空白。您应该使用转换、加载器等通用技术来处理此问题,或者避免切换元素(例如,将标签转换为同一 View 中的输入,而不需要切换 View )

关于javascript - 不了解其容器的主干 View 、通过 AJAX 获取的模型、没有 UI/UX 权衡和可维护的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36710406/

相关文章:

javascript - 我需要添加什么,以便我的 JavaScript 可以按我希望的方式运行?

javascript - 删除 Vuetify 中的默认 v-input-file 图标

javascript - 过滤数组并形成新数组

javascript - 将 JSON 对象插入数组

java - JQuery Address 管理应用程序状态的简单示例

backbone.js - 将多个函数绑定(bind)到 View 的点击事件

javascript - 如何处理事件冒泡?

javascript - JQuery 使用 .on() 添加对象函数

javascript - AJAX 未提交表单

javascript - backbone, javascript mvc - 使用 javascript 设计 View