当前位置: 首页 > Web前端 > vue.js

图解Vue响应式原理

时间:2023-03-31 23:17:47 vue.js

鏈€杩戠郴閲岀殑鍒嗕韩锛屾湁鍚屽鎻愬埌浜哣ue鍝嶅簲寮忓師鐞嗐€傚湪璁ㄨ杩囩▼涓紝鎴戜滑鍙戠幇閮ㄥ垎鍚屽瀵硅繖浜涚煡璇嗙殑鐞嗚В涓嶅娣卞叆锛屾棤娉曞舰鎴愰棴鐜€備负浜嗗府鍔╁ぇ瀹剁悊瑙h繖涓棶棰橈紝鎴戞妸Vue婧愮爜閲嶆柊杩囦竴閬嶏紝鏁寸悊浜嗗嚑涓祦绋嬪浘锛屾柟渚垮ぇ瀹剁悊瑙c€俈ue鍒濆鍖栨ā鏉挎覆鏌撶粍浠舵覆鏌撴湰鏂嘨ue婧愮爜鐗堟湰锛?.6.11锛屼负浜嗕究浜庣悊瑙o紝鍒犳帀浜嗐€傛湰鏂囧皢鎺㈣浠ヤ笅涓や釜鏂归潰锛氫粠Vue鍒濆鍖栧埌绗竴娆℃覆鏌撶敓鎴怐OM鐨勮繃绋嬨€備粠Vue鏁版嵁淇敼鍒伴〉闈㈡洿鏂癉OM鐨勮繃绋嬨€俈ue鍒濆鍖栦粠鏈€绠€鍗曠殑Vue浠g爜寮€濮嬶細杩欐浠g爜寰堢畝鍗曪紝鏈€缁堜細鍦ㄩ〉闈笂鎵撳嵃涓€涓猦elloworld銆傚畠鏄浣曞疄鏂界殑锛熸垜浠粠婧愬ご寮€濮嬪垎鏋愶細newVue銆?/鎵цnewVue鏃讹紝浼氫緷娆℃墽琛屼互涓嬫柟娉?/1.Vue.prototype._init(option)//2.initState(vm)//3.observe(vm._data)//4.newObserver(data)//5.璋冪敤walk鏂规硶閬嶅巻鏁版嵁涓殑姣忎竴涓睘鎬э紝鐩戝惉鏁版嵁鐨勫彉鍖栥€俧unctionwalk(obj){constkeys=Object.keys(obj);for(leti=0;i;constructor(){this.subs=[];}addSub(sub:Watcher){//鏀堕泦姝Watcher瀵硅薄涓娇鐢ㄧ殑鎵€鏈夋暟鎹€倀his.subs.push(sub);}depend(){if(Dep.target){//鏀堕泦渚濊禆锛屾渶鍚庤皟鐢ㄤ笂闈㈢殑addSub鏂规硶Dep.target.addDep(this);}}notify(){constsubs=this.subs.slice();for(leti=0,l=subs.length;i{vm._update(vm._render());};//缁撳悎浠ヤ笂鎴戜滑鍙互寰楀嚭updateComponent浼犲叆Watcher鍐呴儴鍚告皵鍓傛柟娉曘€俷ewWatcher(vm,updateComponent);//7.newWatcher浼氭墽琛學atcher.get鏂规硶//8.Watcher.get浼氭墽琛宼his.getter.call(vm,vm)锛屽嵆鎵цupdateComponent鏂规硶//9.updateComponent浼氭墽琛寁m._update(vm._render())//10.璋冪敤vm._render鐢熸垚铏氭嫙domVue.prototype._render=function():VNode{constvm:Component=this;const{render}=vm.$options;璁﹙node=render.call(vm._renderProxy,vm.$createElement);returnvnode;};//11.璋冪敤vm._update(vnode)娓叉煋铏氭嫙domVue.prototype._update=function(vnode:VNode){constvm:Component=this;if(!prevVnode){//鍒濆娓叉煋vm.$el=vm.__patch__(vm.$el,vnode,hydrating,false);}else{//鏇存柊vm.$el=vm.__patch__(prevVnode,vnode);}};//12銆乿m.__patch__鏂规硶鏄仛domdiff姣旇緝锛岀劧鍚庢洿鏂癲om锛岃繖閲屼笉鍐嶅睍寮€銆傜湅瀹孷ue妯℃澘娓叉煋鐨勬祦绋嬶紝鎴戜滑鍙互寰楀埌濡備笅娴佺▼鍥撅細鑷虫锛屾垜浠煡閬揥atcher鍏跺疄鏄湪Vue鍒濆鍖栭樁娈靛垱寤虹殑锛屽睘浜庣敓鍛藉懆鏈熶腑鐨刡eforeMount浣嶇疆銆俁ender浼氬湪鍒涘缓Watcher鏂规硶鏃舵墽琛岋紝鏈€缁堝皢Vue浠g爜娓叉煋鎴愮湡瀹炵殑DOM銆傛垜浠妸鍓嶉潰鐨勬祦绋嬪啀鏁村悎涓€涓嬶紝鍙互寰楀埌濡備笅娴佺▼锛氫笂鍥惧垎鏋愪簡浠嶸ue鍒濆鍖栧埌娓叉煋DOM鐨勬暣涓祦绋嬨€傛渶鍚庢垜浠啀鍒嗘瀽涓€涓嬶紝褰撴暟鎹彂鐢熷彉鍖栨椂锛孷ue鏄浣曟洿鏂扮殑鍛紵鍏跺疄浠庝笂鍥句篃鍙互鐪嬪嚭锛屽綋Data鍙戠敓鍙樺寲鏃讹紝浼氳皟鐢―ep.notify鏂规硶锛岀劧鍚庤皟鐢╓atcher鍐呴儴鐨剈pdate鏂规硶銆傝鏂规硶浼氬皢鎵€鏈変娇鐢ㄨData鐨刉atcher娣诲姞鍒颁竴涓槦鍒椾腑锛屽苟寮€鍚竴涓紓姝ラ槦鍒桿pdate锛屾渶鍚庢墽琛宊render鏂规硶瀹屾垚椤甸潰鏇存柊銆傛暣浣撴祦绋嬪涓嬶細濂戒簡锛屾帰绱㈠埌杩欓噷锛屾妸Vue鐨勫搷搴斿紡鍘熺悊鍒嗘瀽鐨勫緢閫忓交銆傚鏋滀綘杩樹笉鏄庣櫧锛屼笉濡ㄤ粩缁嗙湅鐪嬩笂鍥俱€傜粍浠舵覆鏌撴湰鏉ュ氨鏄懜绱㈠埌涓婇潰鐨勬祦绋嬪浘锛屼絾鏄ソ濂囧張鎯冲埌浜嗗彟澶栦竴涓棶棰橉煒傘€俈ue缁勪欢鏄浣曟覆鏌撶殑锛熷甫鐫€杩欎釜鐤戦棶锛屾垜缁х画鏌ョ湅婧愮爜銆?/浠庢ā鏉跨紪璇戝紑濮嬶紝褰撴壘鍒拌嚜瀹氫箟缁勪欢鏃讹紝灏嗘墽琛屼互涓嬪嚱鏁?/1.compileToFunctions(template)//2.compile(template,options);//3.constast=parse(template.trim(),options)//4.constcode=generate(ast,options)//5.createElement//6.createComponentexportfunctioncreateComponent(Ctor:Class|Function|Object|void,data:?VNodeData,context:缁勪欢,children:?Array,tag?:string):VNode|鏁扮粍|void{//$options._base瀹為檯涓婃槸鍏ㄥ眬鐨刅ue鏋勯€犲嚱鏁帮紝鍦ㄥ垵濮嬪寲鏃跺湪initGlobalAPI涓畾涔夛細Vue.options._base=VueconstbaseCtor=context.$options._base;//Ctor鏄疺ue缁勪欢涓?script>鏍囩涓嬪鍑虹殑瀵硅薄if(isObject(Ctor)){//缁勪欢涓鍑虹殑瀵硅薄缁ф壙鑷猇ue锛屽緱鍒颁竴涓瀯閫犲嚱鏁?/鐩稿綋浜嶸ue.extend(YourComponent)Ctor=baseCtor.extend(Ctor);}constvnode=newVNode(`vue-component-${Ctor.cid}xxx`);杩斿洖铏氭嫙鑺傜偣锛泒//7.瀹炵幇缁勪欢缁ф壙Vue锛岃皟鐢╒ue._init鏂规硶鍒濆鍖朧ue.extend=function(extendOptions:Object):Function{constSuper=this;甯搁噺Sub=functionVueComponent(options){//璋冪敤Vue.prototype._init锛屽悗缁祦绋嬩笌绗竴娆″姞杞戒竴鑷磘his._init(options);};//鍘熷瀷缁ф壙锛岀瓑鍚屼簬锛欳omponentextendsVueSub.prototype=Object.鍒涘缓锛堣秴绾у師鍨嬶級锛汼ub.prototype.constructor=Sub;杩斿洖瀛愶紱}锛涚湅瀹屼簡缁勪欢娓叉煋鐨勬簮鐮侊紝缁撳悎涓婇潰锛岄噸鏂版暣鐞嗕簡涓€寮犳祦绋嬪浘锛屽浘涓摑鑹查儴鍒嗗氨鏄覆鏌撶粍浠剁殑杩囩▼瀹屾垚浜嗭紝鐜板湪鐪熺殑缁撴潫浜嗭紝鏈€缁堢殑娴佺▼鍥惧氨鏄笂鍥句簡銆傞棶涓棶棰橈紝浣犵幇鍦ㄦ槑鐧絍ue鍝嶅簲寮忕殑鍘熺悊浜嗗悧锛熷鏋滆繕鏄寰楅毦浠ョ悊瑙o紝鎴戣繖閲屼篃鍑嗗浜嗕竴寮犲甫娉ㄨВ鐨勫浘馃槀鎬濊€冧笌鎬荤粨鏈枃浠庢簮鐮佺殑瑙掑害浠嬬粛浜哣ue鍝嶅簲寮忕殑鍘熺悊锛岀畝鍗曞洖椤句竴涓嬨€備粠鏂扮殑Vue寮€濮嬶紝棣栧厛閫氳繃get鍜宻et鐩戝惉Data涓殑鏁版嵁鍙樺寲锛屽垱寤轰竴涓狣ep鏉ユ敹闆嗕娇鐢―ata鐨刉atcher銆傜紪璇戞ā鏉匡紝鍒涘缓涓€涓猈atcher锛屽皢Dep.target鏍囪瘑涓哄綋鍓嶇殑Watcher銆傜紪璇戞ā鏉挎椂锛屽鏋滀娇鐢ㄥ埌Data涓殑鏁版嵁锛屼細瑙﹀彂Data鐨刧et鏂规硶锛岀劧鍚庤皟鐢―ep.addSub鏀堕泦Watcher銆傚綋鏁版嵁鏇存柊鏃讹紝浼氳Е鍙慏ata鐨剆et鏂规硶锛岀劧鍚庤皟鐢―ep.notify閫氱煡鎵€鏈変娇鐢ㄨData鐨刉atcher鏇存柊DOM銆傛渶鍚庯紝濡傛灉浣犲姝ゆ湁浠€涔堟兂娉曪紝娆㈣繋鐣欒█璇勮锛?/p>