Vue.js中的MVVM
生活随笔
收集整理的這篇文章主要介紹了
Vue.js中的MVVM
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
MVVM的理解
MVVM拆開來即為Model-View-ViewModel,有View,ViewModel,Model三部分組成。View層代表的是視圖、模版,負(fù)責(zé)將數(shù)據(jù)模型轉(zhuǎn)化為UI展現(xiàn)出來。Model層代表的是模型、數(shù)據(jù),可以在Model層中定義數(shù)據(jù)修改和操作的業(yè)務(wù)邏輯。ViewModel層連接Model和View。在MVVM的架構(gòu)下,View層和Model層并沒有直接聯(lián)系,而是通過ViewModel層進(jìn)行交互。ViewModel層通過雙向數(shù)據(jù)綁定將View層和Model層連接了起來,使得View層和Model層的同步工作完全是自動的。因此開發(fā)者只需關(guān)注業(yè)務(wù)邏輯,無需手動操作DOM,復(fù)雜的數(shù)據(jù)狀態(tài)維護(hù)交給MVVM統(tǒng)一來管理。在Vue.js中MVVM的體現(xiàn):
MVVM的原理
在不同的框架當(dāng)中,MVVM實現(xiàn)的原理是不同的:
臟檢查機制:
Angular.js就是采取的臟檢查機制,當(dāng)發(fā)生了某種事件(例如輸入),Angular.js會檢查新的數(shù)據(jù)結(jié)構(gòu)和之前的數(shù)據(jù)結(jié)構(gòu)是否發(fā)生來變動,來決定是否更新視圖。
數(shù)據(jù)劫持
Vue.js的實現(xiàn)方式,對數(shù)據(jù)(Model)進(jìn)行劫持,當(dāng)數(shù)據(jù)變動時,數(shù)據(jù)會出發(fā)劫持時綁定的方法,對視圖進(jìn)行更新。
相同點
臟檢查機制和數(shù)據(jù)劫持是有許多相同點的,例如,它們都有三個步驟:
- 解析模版
- 解析數(shù)據(jù)
- 綁定模版與數(shù)據(jù)
實現(xiàn)MVVM
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Two-way data-binding</title> </head> <body><div id="app"><input type="text" v-model="text">{{ text }}</div><script>function observe (obj, vm) {Object.keys(obj).forEach(function (key) {defineReactive(vm, key, obj[key]);});}function defineReactive (obj, key, val) {var dep = new Dep();Object.defineProperty(obj, key, {get: function () {if (Dep.target) dep.addSub(Dep.target);return val},set: function (newVal) {if (newVal === val) returnval = newVal;dep.notify();}});}function nodeToFragment (node, vm) {var flag = document.createDocumentFragment();var child;while (child = node.firstChild) {compile(child, vm);flag.appendChild(child);}return flag;}function compile (node, vm) {var reg = /\{\{(.*)\}\}/;// 節(jié)點類型為元素if (node.nodeType === 1) {var attr = node.attributes;// 解析屬性for (var i = 0; i < attr.length; i++) {if (attr[i].nodeName == 'v-model') {var name = attr[i].nodeValue; // 獲取v-model綁定的屬性名node.addEventListener('input', function (e) {// 給相應(yīng)的data屬性賦值,進(jìn)而觸發(fā)該屬性的set方法vm[name] = e.target.value;});node.value = vm[name]; // 將data的值賦給該nodenode.removeAttribute('v-model');}}new Watcher(vm, node, name, 'input');}// 節(jié)點類型為textif (node.nodeType === 3) {if (reg.test(node.nodeValue)) {var name = RegExp.$1; // 獲取匹配到的字符串name = name.trim();new Watcher(vm, node, name, 'text');}}}function Watcher (vm, node, name, nodeType) {// this為watcher函數(shù)Dep.target = this;// console.log(this);this.name = name;this.node = node;this.vm = vm;this.nodeType = nodeType;this.update();Dep.target = null;}Watcher.prototype = {update: function () {this.get();if (this.nodeType == 'text') {this.node.nodeValue = this.value;}if (this.nodeType == 'input') {this.node.value = this.value;}},// 獲取daa中的屬性值get: function () {this.value = this.vm[this.name]; // 觸發(fā)相應(yīng)屬性的get}}function Dep () {this.subs = []}Dep.prototype = {addSub: function(sub) {this.subs.push(sub);},notify: function() {this.subs.forEach(function(sub) {sub.update();});}};function Vue (options) {this.data = options.data;var data = this.data;observe(data, this);var id = options.el;var dom = nodeToFragment(document.getElementById(id), this);// 編譯完成后,將dom返回到app中document.getElementById(id).appendChild(dom);}var vm = new Vue({el: 'app',data: {text: 'hello world'}});</script> </body> </html> 復(fù)制代碼 超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的Vue.js中的MVVM的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell 变量定义使用
- 下一篇: Error与RuntimeExcepti