JavaScript之實現一個簡單的Vue
Object.defineProperty()
實現之前我們得先看一下Object.defineProperty的實現,因為vue主要是通過數據劫持來實現的,通過get、set來完成數據的讀取和更新。
var obj = {name:‘wclimb‘}
var age = 24
Object.defineProperty(obj,‘age‘,{
enumerable: true, // 可枚舉
configurable: false, // 不能再define
get () {
return age},
set (newVal) {
console.log(‘我改變了‘,age +‘ -> ‘+newVal);
age = newVal
}
})> obj.age
> 24> obj.age = 25;
> 我改變了 24 -> 25
> 25
從上面可以看到通過get獲取數據,通過set監聽到數據變化執行相應操作,還是不明白的話可以去看看Object.defineProperty文檔。
流程圖
圖片描述(最多50字)
html代碼結構
<div id="wrap">
<p v-html="test"></p><input type="text" v-model="form">
<input type="text" v-model="form">
<button @click="changeValue">改變值</button>
{{form}}
</div>
js調用JavaScript
new Vue({
el: ‘#wrap‘,
data:{
form: ‘這是form的值‘,
test: ‘<strong>我是粗體</strong>‘,},
methods:{
changeValue(){
console.log(this.form)
this.form = ‘值被我改變了,氣不氣?‘
}
}
})
Vue結構class Vue{ constructor(){} proxyData(){} observer(){} compile(){} compileText(){} } class Watcher{ constructor(){} update(){} }
Vue constructor 構造函數主要是數據的初始化
proxyData 數據代理
observer 劫持監聽所有數據
compile 解析dom
compileText 解析dom裏處理純雙花括號的操作
Watcher 更新視圖操作
Vue constructor 初始化class Vue{ constructor(options = {}){ this.$el = document.querySelector(options.el); let data = this.data = options.data; // 代理data,使其能直接this.xxx的方式訪問data,正常的話需要this.data.xxx Object.keys(data).forEach((key)=> { this.proxyData(key); }); this.methods = obj.methods // 事件方法 this.watcherTask = {}; // 需要監聽的任務列表 this.observer(data); // 初始化劫持監聽所有數據 this.compile(this.$el); // 解析dom } }
上面主要是初始化操作,針對傳過來的數據進行處理
proxyData 代理data
class Vue{
constructor(options = {}){
......
}
proxyData(key){
let that = this;
Object.defineProperty(that, key, {
configurable: false,
enumerable: true,
get () {
return that.data[key];
},
set (newVal) {
that.data[key] = newVal;
}
});
}
}
上面主要是代理data到最上層,this.xxx的方式直接訪問data
observer 劫持監聽
class Vue{
constructor(options = {}){
......
}
proxyData(key){
......
}
observer(data){
let that = this
Object.keys(data).forEach(key=>{
let value = data[key]
this.watcherTask[key] = []
Object.defineProperty(data,key,{
configurable: false,
enumerable: true,
get(){
return value
},
set(newValue){
if(newValue !== value){
value = newValue
that.watcherTask[key].forEach(task => {
task.update()
})
}
}
})
})
}
}
同樣是使用Object.defineProperty來監聽數據,初始化需要訂閱的數據。
把需要訂閱的數據到push到watcherTask裏,等到時候需要更新的時候就可以批量更新數據了。
JavaScript之實現一個簡單的Vue