利用 ES6 的字符串模板和 JQuery 简单理解 MVVM
把自己对这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 相对传统的写法的最大的优势:
-
视图和模型的分离,视图可以独立模型进行开发;只需约定模型的结构即可。
-
双向数据绑定,视图和模型可以通过VM互相改变。
-
基于约定俗成的模式,可以将烂代码控制在最小范围内,也很难写出烂代码。
ps: 按照我的理解 Angular 中对于基础的VM进行了封装,所以在模板中绑定数据之后,数据更新,会自动更新视图。