利用 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進行了封裝,所以在模板中綁定數據之后,數據更新,會自動更新視圖。