思路:
1.model影響檢視:編譯時註冊watcher,在註冊watcher,呼叫get,通過observer資料劫持get方法,將多個觀察者統一管理起來。當改變資料時,呼叫set方法,將收攏的對應觀察者的upadte方法更新。
2.檢視影響model:編譯時註冊wather,node節點繫結對應的事件,事件觸發時,更改資料模型。
複製**
js模擬實現mvvm
mvvm.js,集中統一;供外呼叫;
class
mvvm
}//將data的屬性掛載到例項上,這樣就可以取this.***了l
proxydata(data),
set(newval)
})})
}}複製**
observe.js,資料劫持;收攏watcher統一管理;通知watcher更新;class
observer()
//資料劫持(這裡我們只處理物件{}的監聽)
observe(data)
if(!data || object.prototype.tostring.call(data) !='[object object]');
object.keys(data).foreach(key=>)
}//資料響應式 defineproperty
definereactive(obj,key,value),
set(newvalue)}})
}}//觀察者模式,統一對watcher進行管理
class
dep()
//新增watcher
addsub(watcher)
//通知所有watcher更新
notify())
}}複製**
compile.js,元素和資料進行編譯,首次渲染檢視;建立watcher,定義資料變化後如何更改檢視;繫結事件,定義檢視變化如何更改modelclass
compile
},替換成model對應的資料;建立watcher,定義資料更新如何更新;繫結事件,定義檢視變化如何更改model;
this.complile();
//3.把編譯好的fragment放回頁面中}}
/*輔助方法*/
//驗證是不是node節點
iselementnode()
//驗證是不是指令
iddirective(name)
/*核心方法*/
//將真實dom轉移到記憶體中,fragment,真實dom就不存在了;
node2fragment(el)
return fragment;
}//遞迴編譯
compile(fragment)else })}
//編譯元素節點
compileelement(node),1:}
array.from(attrs).foreach(attr=>})}
//編譯文字節點
compiletext(node)}} ; }
let reg = /\]+)}\}/g;
//判斷是不是 包含}表示式
if(reg.test(expr))
}}compileutil = ,vm.$data)
}//文字節點的內容進行編譯
gettextval(vm,expr)}};} 多種文字方式
let reg = /\]+)}\}/g;
return expr.replace(reg,(...args)=>)
}//修改例項上的資料
setval(vm,expr,value)
return prev[next]
},vm.$data)
}//輸入框處理 v-mode
model(node,vm,expr))
//繫結事件,檢視變化 影響資料
node.addeventlistener('input',(e)=>)
}//文字處理
//expr=> 例如}} ; } 考慮多種文字方式
text(node,vm,expr)]+)}\}/g;
expr.replace(reg,(...args)=>}}這種文字節點,其中乙個改變就需要將該文字節點渲染一次,就需要重新根據expr }}去重新渲染整個文字節點,所以用的是this.gettextval(vm,expr),而不是newvalue;
updatefn && updatefn(node,this.gettextval(vm,expr));
})})
}updater:
//輸入框更新
modelupdater(node,value)
}}複製**
watcher.js ,建立觀察者,編譯過程中每遇到乙個表示式或者v-model指令,就建立乙個觀察者。 每乙個資料 對應多個觀察者calss watcher
getval(vm,expr),vm.$data)
}get()
//對外報漏的方法,當資料發生改變在observer set方法中,會呼叫sub的notify方法,nofity方法將所有watcher執行update方法
update()
}}複製**
Vue 實現mvvm框架
observe obj 訂閱 key 資料 if this.binding key let binding this.binding key 重寫getter,setter object.defineproperty obj,key,set newval proxydata data,vm set ...
仿照vue實現簡易的MVVM框架(二)
實現文字插值與s for迴圈模版。對於文字插值的實現,我採用正則去匹配還原這個dom節點,以插值 形式為分界,將這個dom節點的文字分割成多個字串,儲存在this.muscha中,再者,將普通文字字串以陣列形式儲存在string屬性中,將插值存放在text屬性值。當然,拼接的時候要明白先從strin...
仿照vue實現簡易的MVVM框架(一)
主要的方法有 compile 深度遍歷前端介面的節點,將其複製進乙個addquene佇列中 pasers 遍歷所有的節點,並將節點包裝成乙個含有本節點 自定義屬性及屬性值的物件。要想實現雙向繫結,重要的一步是,為自定義s model的節點繫結事件 input框的雙向繫結,監聽oninput事件 ob...