可能會覺得這個實現有點長,但我認為這是包含vue基礎框架中響應式原理最核心的一些部分,除了虛擬dom與服務端渲染與跨平台,這將是學習原始碼的必經之路,而我也是剛剛走到這一步。
實現**位址
不理解watcher、observer、dep可以參考這篇 增加
var uid =0;//唯一標識id
// const queue= ; 排隊更新的watcher佇列
// const has = {}; watcher佇列所有id
// index=0; 當前正在更新的watcher位置
// let waiting = false 需要等到watcher佇列所有更新完後,防止重複更新
// let flushing = false 是否正在更新
class vue
initdata(vm)
new observer(this._data) //為data中的資料新增getter和setter,本實現只支援了單層簡單物件
} initmethods(vm,methods)else
vm[key] = methods[key].bind(vm) //**methods的呼叫,可使method直接用this呼叫
}} compile(node)else if(attrs[i].indexof('v-')>=0)}}
if(node.childnodes&&node.childnodes.length>0))
}}else if(node.nodetype == 3)
} proxy(vm,source,key),
set:function(val)
}object.defineproperty(vm,key,sharedconfig)
} compiletext(textnode,vm)\}/g; //原始碼中匹配}的正則
let textcache = textnode.textcontent; //快取純文字內容
if(match = textcache.match(regx))}
let keyarr = ; //記錄所有其中的變數名,不支援表示式和運算子,只支援純變數
match.foreach((item)=>}文字)
textcache =textcache.replace(item,'}')
keyarr.push(item.slice(2,-2))
})let resttxtarr = textcache.split('}');//獲取其它文字陣列
//該函式時通過watcher設定的更新函式,每次依賴改變都會呼叫
updatetextcontent = function(_this))
contenttext += resttxtarr[resttxtarr.length-1]
textnode.textcontent = contenttext //更新到節點文字
}//設定純文字的renderwatcher,原始碼中只設定了乙個renderwatcher,因為它的更新函式很全面,
//我們這裡只針對部分,所以每個需要更新資料到不同型別dom都需要設定乙個對應watcher,就像
//下面的input更新
new watcher(vm,updatetextcontent,null);
}} compileevent(nodeele,attr,vm)
} compiledirective(nodeele,attr,vm)
new watcher(vm,updatenodeval,null);//設定input的更新watcher
nodeele.addeventlistener('change',function(val))
nodeele.removeattribute(attr) //刪除v-model屬性}}}
class watcher
get()
//收集依賴,原始碼定義了依賴的快取,通過對比差別通知某依賴我已經不需要依賴你了,讓它刪掉自己
//我們不需要那麼詳細就不加了
adddep(dep)
} // update()else
// queue.splice(i + 1, 0, this)
// }
// }
// if (!waiting))
// for(index = 0;index)
} definereactive(obj,key,val)
// cater for pre-defined getter/setters
var getter = property && property.get;//記錄已有的getter,setter
var setter = property && property.set;
//第三個引數表示預設值,一般vm.$set()使用,前面這個判斷不知道是為什麼,了解的可以說下
if ((!getter || setter) && arguments.length === 2)
// 子屬性是物件則遞迴,相當於每個dep對應乙個物件
// var childob = !shallow && observe(val);
object.defineproperty(obj, key,
// }
}return value
},set: function reactivesetter (newval)
/* eslint-enable no-self-compare */
// if (process.env.node_env !== 'production' && customsetter)
// #7981: for accessor properties without setter
//這裡給出了issue號,我也沒看的太明白,英語好的可以去看看,
//感覺可能是設定了getter但不設定setter就視為唯讀,也可能和上面那個判斷有關係
if (getter && !setter)
if (setter) else
//為子物件屬性新增getter,setter
// childob = !shallow && observe(newval);
dep.notify(); //通知變化}})
} definereactive******(obj,key,val)
return value
},set:function(newval)
})}}
new vue(
},methods:
this.count = parseint(this.count)+1;
}}})
簡易版Vue響應式流程原始碼實現
1 使用 new vue vhtml vhtml methods changeobject 2 需要實現 class vue 屬性 proxy data set v 需實現 響應式處理 class observer else walk data object.keys data foreach ke...
vue的響應式實現原理
vue2.0的雙向資料繫結主要實現方式就是 發布訂閱 資料劫持 這裡來手寫乙個實現過程,發布訂閱 資料劫持 訂閱器模型 let dep 為何不是陣列?深拷貝與淺拷貝,使用陣列需要key來進行查值 新增訂閱者 listen function key,fn 發布訊息 trigger function v...
vue的響應式
資料變化,頁面就會重新渲染 div const vm newvue 這時候我們在頁面的控制台裡面修改資料 vm.msg hello vue 這時候我們發現,頁面改變了。為什麼data裡面的資料會直接出現在vue例項物件中?當建立vue例項時,vue會將data中的資料 給vue例項,目的是為了實現響...