摘要:響應(yīng)式原理作為寫業(yè)務(wù)的碼農(nóng),幾乎不必知道原理。所以找工作之前可以先復(fù)習(xí)下,只要是關(guān)于的,必定會(huì)問響應(yīng)式原理。如果是,運(yùn)行其方法,其方法中含有的值時(shí),會(huì)觸發(fā)收集當(dāng)更新時(shí),也會(huì)觸發(fā)更新重新獲取值如果是會(huì)觸發(fā)的函數(shù)響應(yīng)式原理計(jì)算屬性值這是
Vue響應(yīng)式原理
作為寫業(yè)務(wù)的碼農(nóng),幾乎不必知道原理。但是當(dāng)你去找工作的時(shí)候,可是需要造原子彈的,什么都得知道一些才行。所以找工作之前可以先復(fù)習(xí)下,只要是關(guān)于vue的,必定會(huì)問響應(yīng)式原理。
核心:
//es5 Object.defineProperty(obj,key,{ get() { // 獲取obj[key]的時(shí)候觸發(fā) }, set(val) { // obj[key] = "xxx"時(shí)觸發(fā) } })
其實(shí),只需要在修改data值的時(shí)候,需要觸發(fā)一個(gè)回調(diào)方法,來更新與此值有關(guān)的數(shù)據(jù),就完了。但是你面試的時(shí)候,那些大佬可不會(huì)覺得是這樣的,需要把整個(gè)流程說明白才行。
簡(jiǎn)單的Vue響應(yīng)式代碼如下: Vue.js:class Vue { constructor(opts) { this.opts = opts if (opts.data) this.initData(opts.data); if (opts.watch) this.initWatch(opts.watch); if (opts.computed) this.initComputed(opts.computed); if (opts.el) this.$mount(opts.el) } initData(data) { // 讓data上的數(shù)據(jù)被get的時(shí)候能夠搜集watcher,data變?yōu)橛^察者 new Observable(data); this.data = data // 數(shù)據(jù)可在this上直接讀取 Object.keys(data).forEach(key => { this.proxy(key) }) } initWatch(watch) { Object.keys(watch).forEach(key => { // new Watcher(this, key, watch[key]) }) } initComputed(data) { Object.keys(data).forEach(key => { new Watcher(this, key) this.proxy(key, { get: data[key], }) }) } $mount(el) { el = document.querySelector(el) this.template = el.innerHTML this.el = el const fn = _ => { const nwTemp = this.parseHTML(this.template) this.el.innerHTML = nwTemp if(this.opts.mounted) { this.opts.mounted.call(this) } } new Watcher(this, fn) } parseHTML(template) { return template.replace(/{{(.*?)}}/g, (str, str1) => { return this[str1.trim()] }) } // 將數(shù)據(jù)直接掛到this上,使用getterSetter代理,獲取vm.data上的值 proxy(key, getterSetter) { const vm = this getterSetter = getterSetter || { set(value) { vm.data[key] = value }, get() { return vm.data[key] } } Object.defineProperty(vm, key, getterSetter) } } // 給data作為觀察者用的 class Observable { constructor(obj) { Object.keys(obj).forEach(key => { this.defineReact(obj, key, obj[key]) }); } defineReact(obj, key, value) { const dep = new Dep() Object.defineProperty(obj, key, { get() { // 獲取data里面信息的時(shí)候,能夠搜集依賴,這些依賴都是watcher實(shí)例 if (Dep.target) { dep.append(Dep.target) } return value }, set(val) { value = val // 修改data里面數(shù)據(jù)的時(shí)候,去通知已搜集的依賴更新 dep.notify() } }) } } // 搜集與觸發(fā)wacher class Dep { constructor() { this.subs = [] } append(watcher) { // 避免重復(fù)添加watcher // watcher 在update的時(shí)候,會(huì)重新獲取值,此時(shí)不必再添加 if(this.subs.includes(watcher)) return this.subs.push(watcher) } notify() { this.subs.forEach(watcher => { watcher.update() }) } } Dep.target = null class Watcher { // keyOrFn 為字符串或者function,opts.watch為字符串,computed,$mount中為function constructor(vm, keyOrFn, cb) { this.cb = cb if (typeof keyOrFn === "string") { this.getter = function () { return vm[keyOrFn] // 例:initWatch時(shí),watch:{a(){}} ,a為data里的數(shù)據(jù),此處獲取vm.a會(huì)觸發(fā)a的收集 } } else { this.getter = keyOrFn // 如果為fn(computed中)值為此函數(shù)的返回值 } this.value = this.get() } get() { Dep.target = this // 此watcher記錄下來 const value = this.getter(this.vm) // 運(yùn)行g(shù)etter,如果是watch,獲取一次data里的值,完成收集。 // 如果是computed,運(yùn)行其方法,其方法中含有data的值時(shí),會(huì)觸發(fā)收集 // 當(dāng)更新時(shí),也會(huì)觸發(fā)getter Dep.target = null return value } update() { // 更新 const oldValue = this.value // 重新獲取值 this.value = this.get() if (this.cb) { //如果是watch,會(huì)觸發(fā)watch的函數(shù) this.cb.call(this.vm, this.value, oldValue) } } }index.html
Vue響應(yīng)式原理
msg: {{ msg }}
num: {{ num }}
num+1計(jì)算屬性值:{{ add1 }}
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104174.html
摘要:工程實(shí)踐立足實(shí)踐,提示實(shí)際水平內(nèi)聯(lián)函數(shù)與性能很多關(guān)于性能優(yōu)化的文章都會(huì)談及內(nèi)聯(lián)函數(shù),其也是常見的被詬病為拖慢性能表現(xiàn)的元兇之一不過本文卻是打破砂鍋問到底,論證了內(nèi)聯(lián)函數(shù)并不一定就會(huì)拖慢性能,過度的性能優(yōu)化反而會(huì)有損于應(yīng)用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...
摘要:深入學(xué)習(xí)作為配合使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。至此,構(gòu)造函數(shù)部分已經(jīng)過了一遍了。 深入學(xué)習(xí)Vuex vuex作為配合vue使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。本文以使用者的角度,結(jié)合源碼來學(xué)習(xí)vuex。其中也參考了許多前輩的文章,參見最后的Reference Vue加載Vuex...
摘要:深入學(xué)習(xí)作為配合使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。至此,構(gòu)造函數(shù)部分已經(jīng)過了一遍了。 深入學(xué)習(xí)Vuex vuex作為配合vue使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。本文以使用者的角度,結(jié)合源碼來學(xué)習(xí)vuex。其中也參考了許多前輩的文章,參見最后的Reference Vue加載Vuex...
閱讀 4013·2021-11-18 13:22
閱讀 1831·2021-11-17 09:33
閱讀 2887·2021-09-26 09:46
閱讀 1220·2021-08-21 14:11
閱讀 2896·2019-08-30 15:53
閱讀 2717·2019-08-30 15:52
閱讀 1915·2019-08-30 10:52
閱讀 1528·2019-08-29 15:30