利用 ES6 的字符串模板和 JQuery 简单理解 MVVM

jopen 8年前

把自己对这MVVM设计模式的理解整理并记录,仅作自己以后查询之用。

先说前端为什么需要 MVVM 或者 FLUX。在我看来,是为了保证不那么优秀的前端er在团队中写出不那么垃圾的代码,即使确实十分垃圾,也不会污染到团队中其他同事的代码,其它的设计模式应该也具有这种作用。

通过代码对比理解MVVM

MVVM 是 Model-View-ViewModel (双向数据绑定)的简写。不管是 MVVM 或者是 FLUX, 都强调的是视图和数据的分离。MVVM 是将视图和数据分离之后,通过 ViewModel 将数据和视图进行绑定。

View 一般是指模板,例如 Handlerbars ,或者 ES6 的字符串模板,写法如下:

let message = 'hello,world!!'  let demo = `  <div id="demo">      <p>${message}</p>  </div>  `

然后通过 jQuery 插入 body 中

$('body').html(demo)

对于 demo 便是View,message 是此 View 指定的 Model。由于在这个例子中并没有交互,仅仅只是为了说明视图和模型, 所以并没有 VM 部分。

下面的例子是一个完整的用 JQuery 实现的 MVVM 模式写法

//------ Model  let model = {    value: 1,    fns: [],    set: function(v) {      this.value = v      this.fns.forEach(fn => fn.call(this, this.value))    },    on: function(fn) {      this.fns.push(fn)    }  };      //------ View  let demo = `  <div>  <p>${model.value}</p>  <input value='${model.value}' />  <button id="button1">+1</button>  </div>  `    $('body').html(demo)    //------ ViewModel    $('input').on('keyup', function() {      model.set($(this).val()|0)  })      $('button#button1').on('click', function() {      model.set(model.value + 1)  })      model.on(function(value) {    $('p').html(value)    $('input').val(value)  })

在这个例子中, input输入的内容会实时显示在p标签中,而button被点击之后,也会对p标签的值和input标签的值都做+1处理;如果我们按照通常的 jQuery 来处理的话应该怎么做?

$('input').on('keyup', function() {    let value = $(this).val()|0;    $('p').html(value)    $('input').val(value)  })    $('button').on('click', function() {      let value = $('input').val()|0 + 1;      $('p').html(value)      $('input').val(value)  })

从这两段代码来看,并没有太大区别,甚至下面一段代码看起来更短。然而下面一段代码将 视图和模型的处理写到了一起,试想一下,当我们想再增加一个 -1 的button 呢?对于 MVVM的模式,只要再写

<button id='button2'>-1</button>  $('button#button2').on('click', function() {      model.set(model.value - 1)  })

即可。

而对于传统的方式,还需要先取得当前input值或p的值,然后再进行-1操作,最后还需要将input和p的innerHTML都修改一次。随着DOM的增加,处理难度的差距越来越大,越来越不容易理解,修改一次,如履薄冰。

通过这个小例子可以看出 MVVM 相对传统的写法的最大的优势:

  1. 视图和模型的分离,视图可以独立模型进行开发;只需约定模型的结构即可。

  2. 双向数据绑定,视图和模型可以通过VM互相改变。

  3. 基于约定俗成的模式,可以将烂代码控制在最小范围内,也很难写出烂代码。

ps: 按照我的理解 Angular 中对于基础的VM进行了封装,所以在模板中绑定数据之后,数据更新,会自动更新视图。