更新Backbone.js查看变得一团糟

Jac*_*ack 3 backbone.js

鉴于一个模型:

MyModel = Backbone.Model.extend({
  defaults: {
    name: '',
    age: -1,
    height: '',
    description: ''
  }
});
Run Code Online (Sandbox Code Playgroud)

和一个视图将模型呈现为列表:

MyView  = Backbone.View.extend({
  tagName: 'ul',
  className: 'MyView',

  render() {
    var values = {
      name: this.model.get('name'),
      age: this.model.get('age'),
      height: this.model.get('height'),
      description: this.model.get('description')
    }

    var myTemplate = $('#MyView-Template').html();
    var templateWithValues = _.template(myTemplate , values);
  }
});
Run Code Online (Sandbox Code Playgroud)

以及View加载的模板:

<script type="text/template" id="MyView-Template">  
  <li class="name"><%= name %></li>
  <li class="age"><%= age %></li>
  <li class="name"><%= height%></li>
  <li class="name"><%= description%></li>
</script>
Run Code Online (Sandbox Code Playgroud)

一切正常,虽然这是一个人为的例子,真正的代码在模型中有很多很多属性.我遇到的问题是如何处理模型的更新.

我创建了一个HTML表单,其中包含每个字段的相应输入元素.表单被建模并作为模板加载:

<script type="text/template" id="MyEditView-Template">  
  <input type"text" value="<%= name %>" /> <br />
  <input type"text" value="<%= age%>" /> <br />
  <input type"text" value="<%= height%>" /> <br />
  <input type"text" value="<%= description%>" /> 
</script>
Run Code Online (Sandbox Code Playgroud)

并加载到视图中:

MyEditView  = Backbone.View.extend({
      tagName: 'form',
      className: 'MyEditView',

      render() {
        var values = {
          name: this.model.get('name'),
          age: this.model.get('age'),
          height: this.model.get('height'),
          description: this.model.get('description')
        }

        var myTemplate = $('#MyEditView-Template').html();
        var templateWithValues = _.template(myTemplate , values);
      }
    });
Run Code Online (Sandbox Code Playgroud)

当用户保存表单时,新值将在模型(MyModel)中设置.但是我不想重新渲染整个原始视图,它需要太长时间并且有许多嵌套元素.我只想更新模型中值已更改的HTML元素.

问题是我如何优雅地将模型的属性链接到HTML元素,以便我可以对已经渲染的视图执行以下操作:

  1. 迭代模型的属性.
  2. 确定已修改的属性.
  3. 仅更新已修改属性的UI.
  4. 隐藏任何先前呈现的属性的UI,这些属性不应再显示.

我有一个相当难看的JavaScript查找表(只是一个对象)的解决方案,它将属性名称映射到HTML元素字符串:

var AttributesMap = {
    name: {
        htmlRef: 'li.name',
        attributeName: 'name'
    },
    age: {
        htmlRef: 'li.age',
        attributeName: 'age'
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

这感觉很糟糕,导致一些非常臃肿的代码.

Dee*_*ons 6

实际上你的帖子中隐藏着两个问题.您对模型的属性有疑问,并且您不知道如何订阅模型更改事件.幸运的是,使用backbone.js可以轻松实现这两个目标.将您的观看代码更改为以下

1

render: function () {
    var model = this.model;
    $(this.el).empty().html(_.template(this.template, this.model.toJSON()))
    return this;
}
Run Code Online (Sandbox Code Playgroud)

where el是定义容器的视图的属性.toJSON()是一种可以在模型上调用的方法,用于序列化可以通过线路传输的格式.

2

视图应该在其初始化函数中订阅模型更改事件,或者更恰当地使用委托事件支持.当模型属性发生更改时,将change在该模型上调用事件,您可以在此处订阅,例如下面的示例.

window.ListView = Backbone.View.extend({
    initialize: function () {
        //pass model:your_model when creating instance
        this.model.on("change:name", this.updateName, this);
        this.model.on("change:age", this.changedAge, this);
    },
    render: function () {
        var model = this.model;
        $(this.el).empty().html(_.template(this.template, this.model.toJSON()))
        return this;
    },
    updateName: function () {
        alert("Models name has been changed");
    },
    changedAge: function () {
        alert("Models age has been changed");
    }
});
Run Code Online (Sandbox Code Playgroud)

JsBin的例子

http://jsbin.com/exuvum/2