当前位置: 首页 > Web前端 > HTML

面试官:连Vue3响应式系统都不会写,还敢说精通?

时间:2023-03-28 16:25:01 HTML

涔熻浣犳垜绱犳湭璋嬮潰锛屼絾寰堟湁鍙兘鎴戜滑浼氱浉瑙佹櫄銆傛垜鏄墠绔偉澶撮奔銆傚墠瑷€璇翠粖骞存槸宸ヤ綔鏈€宸殑涓€骞淬€傚ぇ鍘傝鍛橈紝灏忓巶璺熼锛屾姇鍑哄嚑鐧句唤绠€鍘嗗苟鍥炲鐨勫瀵ユ棤鍑犮€備笁閲戝洓閾跺ぇ姒傚彉鎴愪簡涓夐摐鍥涢搧锛屽噭鍑夊噭鍑夛紝鍑勫噳鍑勬儴銆傝€屼粖澶╃殑涓昏锛屽皬甯呭悓瀛︼紝鍗村湪閫嗛鐨勭幆澧冧笅缁欎簡闈㈣瘯瀹樹竴涓闈㈢殑鎵撳嚮锛屽ぇ绉€涓€韬紝浼樼濡備粬锛屽埌搴曠粡鍘嗕簡鎬庢牱鐨勯潰璇曪紵鏂囩珷涓殑渚嬪瓙鍜屼唬鐮佸彲浠ョ偣鍑昏繖閲屾煡鐪嬨€?.#鍑洪闈㈣瘯瀹橈細鎴戠湅浣犵殑绠€鍘嗘槸绮鹃€歏ue3骞朵笖鐮旂┒杩囧畠鐨勬簮鐮侊紵骞磋交浜虹柉浜嗭紒鎴戜滑鐜板満琛ㄦ紨鎬庝箞鏍凤紵姣曠珶闈㈣瘯瀹樼幇鍦哄嚭棰樹簡...

灏忓竻鏆楀枩馃構锛氳繖涓畝鍗曪紝灏辨槸鎴彇鐘舵€佸璞★紝鍦ㄥ彇鏂囨湰鍊肩殑鏃跺€欐敹闆嗘晥鏋滃嚱鏁颁緷璧栵紝鐒跺悗鍦ㄥ彇鍊肩殑鏃跺€欐墽琛屼竴娉㈡敹闆嗗埌鐨勬晥鏋滃嚱鏁拌缃枃鏈殑鍊笺€傞潰璇曞畼锛氬搸锛屾垜涔熻锛屽埆閫兼垜锛屽揩鍐欏惂...2Version1:璺戣捣鏉ヤ簡锛屼笉杩囪繕涓嶉€氱敤锛宲awn2.1#婧愮爜瀹炵幇灏忓竻寰堝揩灏卞啓濂戒簡绗竴涓増鏈紝鏍稿績鍦ㄩ偅閲屽彧鏈変袱姝ワ細绗竴姝ワ細鏀堕泦渚濊禆锛堟晥鏋滃嚱鏁帮級锛岃鍙杒ey鏃跺瓨鍌ㄦ晥鏋滃嚱鏁扮浜屾锛氳缃€兼椂锛屾墽琛屼緷璧栵紙鏁堟灉鍑芥暟锛塩onst$app=document.querySelector('#app')constbucket=newSet()conststate=newProxy({text:'hellofatfish'},{get(target,key){constvalue=target[key]//绗竴姝ワ細鏀堕泦渚濊禆锛岃鍙栨椂閿紝瀛樺偍鏁堟灉functionbucket.add(effect)console.log(`get${key}:${value}`)returnvalue},set(target,key,newValue){console.log(`set${key}:${newValue}`)target[key]=newValue//Step2:璁剧疆鍊兼椂锛屼細渚濊禆鎵цbucket.forEach((fn)=>fn())}})functioneffect(){console.log('鎵ц鏁堟灉')$app.innerText=state.text}effect()setTimeout(()=>{state.text='helloVue3'},1000)鏁堟灉棰勮鐐瑰嚮棰勮锛屽搾鍝掑搾锛岀湅璧锋潵寰堢畝鍗曪紝鐬棿鎼炲畾锛?.2#闈㈣瘯瀹樿瘎浠烽潰璇曞畼锛氬姛鑳藉疄鐜颁簡锛屼絾鏄笉鏄緢婊℃剰銆備綘杩欓噷鐨勯泦鍚堜緷璧栨槸涓€涓‖缂栫爜鐨勫嚱鏁板悕鏁堟灉锛屽彧瑕佺◢绋嶆崲涓瘽棰樺氨涓嶈浜嗐€?divid="container">
const$app1=document.querySelector('#app1')const$app2=document.querySelector('#app2')conststate={text:'hellofatfish',text2:'hellofatfish2'}//鏀瑰彉app1functioneffect1()鐨勫€納console.log('executedeffect')$app1.innerText=state.text}//鏀瑰彉app2鐨勫€糵unctioneffect2(){console.log('executedeffect2')$app2.innerText=state.text2}//1绉掑悗涓や釜div鐨勫€奸渶瑕侀渶鍗曠嫭鏇存敼setTimeout(()=>{state.text='helloVue3'state.text2='helloVue3-2'},1000)3#鐗堟湰浜岋細鏀寔澶氬睘鎬у搷搴斿紡淇敼鍜屼富鍔ㄦ敞鍐?.1#sourcecodeRealizing灏忓竻蹇冩兂锛氣€滃ぇ鎰忎簡锛屾垜搴旇涓诲姩閫氳繃鏌愮鏈哄埗灏嗘晥鏋滀緷璧栧嚱鏁版敞鍐屽埌妗朵腑锛岃繖鏍蜂笉绠′綘鏄尶鍚嶅嚱鏁拌繕鏄懡鍚嶅嚱鏁帮紝閮戒竴瑙嗗悓浠併€傗€濅粬寰堣仾鏄庯紝绔嬪埢鎯冲埌浜嗙瓟妗堛€俢onstbucket=newSet()letactiveEffect//鍙樺寲鐐癸細//浣跨敤effect鍑芥暟涓诲姩鏀堕泦渚濊禆consteffect=function(fn){//姣忔鎵ц鏃跺皢褰撳墠fn璧嬪€肩粰activeEffect锛岃繖鏍疯鍙栧湪fn涓Е鍙戞搷浣滄椂琚姄鍙栵紝鍙互鏀堕泦鍒版《涓璦ctiveEffect=fn//涓诲姩鎵ц涓€娆″緢閲嶈锛屽繀涓嶅彲灏慺n()}conststate=newProxy({text:'hellofatfish',text2:'hellofatfish2'},{get(target,key){constvalue=target[key]//鍙樺寲鐐癸細浠庣増鏈?鏁堟灉鏀逛负activeEffect锛屼笉鍐嶄緷璧栧叿浣撶殑鍑芥暟鍚峛ucket銆俛dd(activeEffect)console.log(`get${key}:${value}`)杩斿洖鍊紏,set(target,key,newValue){console.log(`set${key}:${newValue}`)target[key]=newValuebucket.forEach((fn)=>fn())}})effect(functioneffect1(){console.log('executedeffect1')$app1.innerText=state.text})effect(functioneffect2(){console.log('鎵цeffect2')$app2.innerText=state.text2})setTimeout(()=>{state.text='helloVue3'state.text2='helloVue3-2'},1000)鏁堟灉棰勮鍙互鐪嬪埌锛屽湪杩欐1绉掑悗app1鍜宎pp2閮藉彉鎴愪簡瀵瑰簲鐨勫€硷紝鐩殑灏辫揪鍒颁簡銆傜偣鍑绘煡鐪?.2#闈㈣瘯瀹樻劅瑷€闈㈣瘯瀹橈細灏忎紮瀛愪汉寰堝ソ锛屾€濈淮鐏垫椿锛岄€傚簲蹇紒浣嗘槸浣犳湁娌℃湁鎯宠繃涓€涓棶棰橈紵缁欑姸鎬佸姞涓€涓箣鍓嶄笉瀛樺湪鐨勫睘鎬э紝浣嗘槸浣犵殑bucket浼氭妸鏀堕泦鍒扮殑渚濊禆鎵ц涓€娆★紝鏄笉鏄湁鐐规氮璐癸紵鏁堟灉鑳戒笉鑳戒緷璧栦簬state鐨勫€硷紝鍙湁鍊煎彂鐢熷彉鍖栨墠浼氭墽琛屽洖璋冿紵4#鐗堟湰3锛氬啀娆¢噸鏂拌璁♀€滄《鈥濇暟鎹粨鏋?.1#閲嶆柊璁捐鏁版嵁缁撴瀯灏忓竻锛氭劅瑙夋湁鐐规病搴曪紝绠€鍘嗕笂璇寸簿閫歏ue锛岀爺绌惰繃Vue鐨勬簮鐮佹繁搴︼紝濂絋M鐨勫潙锛侀噰璁胯繕寰楃户缁€傝嫤鎬濆啣鎯筹紝缁堜簬鏄庣櫧浜嗙浜屼釜鐗堟湰鐨勯棶棰橈細鏁堟灉鍑芥暟鍜岃鎿嶄綔鐨勭洰鏍囧瓧娈典箣闂存病鏈夋槑纭殑鑱旂郴锛歝onststate=newProxy({text:'hellofatfish'},{get(target,key){constvalue=target[key]//涓嶇璇诲埌`state`鐨勪粈涔堝睘鎬э紝閮戒細鎵ц`get`骞舵敹闆嗗埌`bucket`涓璪ucket.add(effect)returnvalue},set(target,key,newValue){target[key]=newValue//鏃犺`state`鐨勫€艰淇敼浠€涔堬紝閮戒細瑙﹀彂`set`锛屽苟鎵ц鏀堕泦鍒扮殑渚濊禆銆俠ucket.forEach((fn)=>fn())}})1.濡備綍涓烘柊鐨勬槧灏勫叧绯昏璁″瓨鍌ㄥ湪bucket涓殑鍊硷紵鎴戜滑鐪嬩竴涓嬪叧閿唬鐮乪ffect(functioneffectFn(){$app.innerText=state.text})杩欐浠g爜鏈夊嚑涓綔鐢細琚搷浣滐紙璇诲彇锛夌殑浠g悊瀵硅薄鐨勭姸鎬佽鎿嶄綔锛堣鍙栵級鐨勫瓧娈靛悕鏂囨湰浣跨敤effect鍑芥暟娉ㄥ唽鐨別ffectFn鍑芥暟锛岄偅涔堝畠浠箣闂寸殑鍏崇郴鍙互鐢ㄦ爲鐘舵€亅__key|__effectFn2琛ㄧず銆傚満鏅竴锛氭湁涓や釜effectFn鍒嗗埆璇诲彇鍚屼竴涓璞$殑灞炴€у€煎浜庝笂闈㈢殑鏍戝舰缁撴瀯锛岀幇鍦ㄨ〃绀轰负锛歵ext灞炴€у簲璇ヤ笌effectFn1鍜宔ffectFn2鐘舵€佸缓绔嬪叧绯粅__text|__effectFn1|__effectFn23銆傚満鏅簩锛氬湪effectFneffect(functioneffectFn1(){//readtext1andtext2state.textstate.text2})text鍜宼ext2灞炴€т腑璇诲彇鍚屼竴涓璞$殑澶氫釜涓嶅悓灞炴€у簲璇ュ拰effectFn1state|__text|寤虹珛鑱旂郴__effectFn1|__text2|__effectFn14.鍦烘櫙涓夛細鍦ㄤ笉鍚岀殑effectFn涓鍙栦笉鍚屽璞$殑涓嶅悓灞炴€ffect(functioneffectFn1(){//璇诲彇text1state1.text1})effect(functioneffectFn2(){//璇诲彇text2state2.text2})瀵瑰簲鍏崇郴琛ㄧず濡備笅锛歴tate1|__text1|__effectFn1state2|__text2|__effectFn2鐪嬪埌杩欓噷锛岀浉淇′綘涓€瀹氬緢鑱槑鐞嗚В锛屽綋鎴戜滑鏀瑰彉state2.text2鐨勫€兼椂锛屽彧浼氶噸鏂版墽琛宔ffectFn2鍑芥暟锛岃€宔ffectFn1涓嶄細銆傚綋鐒讹紝娣诲姞涔嬪墠涓嶅瓨鍦ㄧ殑灞炴€ф椂锛宔ffectFn1鍜宔ffectFn2閮戒笉浼氭墽琛屻€?.鐢讳釜鏁版嵁缁撴瀯鍥剧悊瑙e瓨鍌ㄥ叧绯伙細4.2#婧愮爜瀹炵幇6锛氭柊婧愮爜瀹炵幇const$app=document.querySelector('#app')//閲嶆柊瀹氫箟bucket鏁版嵁绫诲瀷涓篧eakMapconstbucket=newWeakMap()letactiveEffectconsteffect=function(fn){activeEffect=fnfn()}conststate=newProxy({name:'fatfish',age:100},{get(target,key){constvalue=target[key]//ActiveEffect娌℃湁鍊艰〃绀轰笉鎵цeffect鍑芥暟锛屾棤娉曟敹闆嗕緷璧栵紝鎵€浠ョ洿鎺eturnif(!activeEffect){return}//姣忎釜target閮芥槸bucket涓殑涓€涓狹ap绫诲瀷锛歬ey=>effectsletdepsMap=bucket.get(target)//绗竴娆℃嫤鎴紝depsMap涓嶅瓨鍦紝鍏堝垱寤鸿繛鎺f(!depsMap){bucket.set(target,(depsMap=newMap()))}//鏍规嵁褰撳墠璇诲彇鐨刱ey锛屽皾璇曡鍙栧彇key鐨別ffects鍑芥暟letdeps=depsMap.get(key)if(!deps){//deps鏈川涓婃槸涓€涓猄et缁撴瀯锛宼h涔熷氨鏄锛屼竴涓猭ey鍙互鏈夊涓猠ffect鍑芥暟锛屽涓猠ffect渚濊禆浜巇epsMap.set(key,(deps=newSet()))}//灏嗘縺娲荤殑effectFn瀛樺叆bucket涓璬eps.add(activeEffect)console.log(`get${key}:${value}`)杩斿洖鍊紏,set(target,key,newValue){console.log(`set${key}:${newValue}`)//璁剧疆灞炴€у€紅arget[key]=newValue//璇诲彇缁撴瀯涓簁ey鐨刣epsMap=>effectsconstdepsMap=bucket.get(target)if(!depsMap){return}//瀹為檯璇诲彇渚濊禆浜庡綋鍓嶅睘鎬х殑effectsofthevaluekeyconsteffects=depsMap.get(key)//閫愪釜鎵цeffects&&effects.forEach((fn)=>fn())}})effect(()=>{console.log('鎵ц鏁堟灉')$app.innerText=`浣犲ソ${state.name}锛屼綘${state.age}宀佷簡鍚楋紵`})setTimeout(()=>{state.name='Vue3'state.age=18},1000)鏁堟灉棰勮鐐瑰嚮鏌ョ湅鍙互鐪嬪埌鎴戜滑缁檚tate娣诲姞浜嗕竴涓睘鎬ф枃鏈紝浣嗘槸鏁堟灉骞舵病鏈夋墽琛屻€傚皢name灞炴€ф敼鎴恓uejin鍚庝細鎵ц锛寁iew灞備篃浼氭洿鏂般€?.3#闈㈣瘯瀹樻柟璇勮鐗涢€硷紝鐗涢€硷紝宸偣鎶婃垜闅炬锛屽皬寮熶僵鏈嶏紒浣嗘槸鑳戒笉鑳芥洿杩涗竴姝ワ紝鍙兘瀵箂tate鐨勪竴涓璞″仛react澶勭悊锛岃兘涓嶈兘鍐嶅皝瑁呬竴涓嬶紝鍍廣ue3涓殑reactive涓€鏍蜂娇鐢紵5#鐗堟湰4锛歊eactive鎶借薄锛屾湁鐐瑰儚Vue35.1#婧愮爜瀹炵幇灏忓竻蹇冩兂锛氫綘涓€瀹氭槸涓嶆兂璁╂垜閫氳繃闈㈣瘯锛屾晠鎰忓垇闅炬垜锛屼絾浣犳槸闈㈣瘯瀹橈紝浣犳槸鏈€澶х殑銆傚幓鍋氬氨瀵逛簡銆備箣鍓嶆垜浠凡缁忓疄鐜颁簡鍩烘湰鐨勫搷搴斿紡鍔熻兘锛屼絾鏄负浜嗘硾鍖栵紝鎴戜滑鍙互杩涗竴姝ュ皝瑁呫€俢onstbucket=newWeakMap()//閲嶆柊瀹氫箟bucket鏁版嵁绫诲瀷涓篧eakMapletactiveEffectconsteffect=function(fn){activeEffect=fnfn()}//track琛ㄧず璺熻釜鍑芥暟track(target,key){//activeEffectNonevalue琛ㄧず涓嶆墽琛宔ffect鍑芥暟锛屾棤娉曟敹闆嗕緷璧栵紝鐩存帴returntarget)//绗竴娆℃嫤鎴紝濡傛灉depsMap涓嶅瓨鍦紝鍏堝垱寤鸿繛鎺f(!depsMap){bucket.set(target,(depsMap=newMap()))}//鏍规嵁褰撳墠璇诲彇鐨刱ey锛屽皾璇曡鍙栨寜閿晥鏋滃嚱鏁發etdeps=depsMap.get(key)if(!deps){//deps鏈川涓婃槸涓€涓猄et缁撴瀯锛屽嵆涓€涓寜閿彲浠ユ湁澶氫釜鏁堟灉鍑芥暟锛屽涓晥鏋滀緷璧栦簬depsMap.set(key,(deps=newSet()))}//灏嗘縺娲荤殑effectFn瀛樺叆bucket涓璬eps.add(activeEffect)}//瑙﹀彂鎵ц鍙栧喅浜庡嚱鏁皌rigger(target,key){//璇诲彇缁撴瀯涓簁ey=>effects鐨刣epsMapconstdepsMap=bucket.get(target)if(!depsMap){return}//瀹為檯璇诲彇渚濊禆浜庡綋鍓嶅睘鎬у€肩殑effectskeyconsteffects=depsMap.get(key)//涓€涓竴涓墽琛宔ffects&&effects.forEach((fn)=>fn())}//缁熶竴鏆撮湶鍙嶅簲鍑芥暟functionreactive(state){returnnewProxy(state,{get(target,key){constvalue=target[key]track(target,key)console.log(`get${key}:${value}`)杩斿洖鍊紏,set(target,key,newValue){console.log(`set${key}:${newValue}`)//璁剧疆灞炴€у€紅arget[key]=newValuetrigger(target,key)}})}withThe涓婇潰鐨勫寘鎴戜滑鐢ㄨ捣鏉ョ湡鐨勬湁鐐瑰儚Vue3鐨勬劅瑙夛紒const$app=document.querySelector('#app')constnameObj=reactive({name:'fatfish'})constageObj=reactive({age:100})effect(()=>{console.log('鎵цeffect')$app.innerText=`浣犲ソ${nameObj.name}锛屼綘${ageObj.age}宀佷簡鍚楋紵`})setTimeout(()=>{nameObj.name='Vue3'},1000)setTimeout(()=>{ageObj.age=18},2000)鏁堟灉棰勮鐐瑰嚮棰勮鍙互鐪嬪埌鎴戜滑閫氳繃reactive瀹氫箟浜嗕袱涓搷搴斿紡鏁版嵁锛?绉掑悗淇敼nameObj鐨勫€硷紝瑙嗗浘绔嬪嵆鏇存柊锛?绉掑悗,淇敼ageObj鐨勫€硷紝绔嬪嵆鏇存柊瑙嗗浘杩欎釜澶熼€氱敤浜嗗惂锛佸畬缇?.2#闈㈣瘯瀹樼偣璇勯潰璇曞畼锛氫綘寰堝ソ锛屼絾鏄€︹€﹀皬甯咃細鍙槸浣犲濡癸紒鎴戝垰鍒氶潰璇曪紝浣犺鎴戝缓涓€涓猇ue3鍚楋紵闈㈣瘯瀹橈細濂藉惂濂藉惂鍝堝搱鍝堬紒杩欒疆闈㈣瘯宸茬粡杩囧幓浜嗭紝鎺ヤ笅鏉ョ殑闈㈣瘯瀹樹細缁х画璁╀綘瀹炴柦鏇村叏闈㈢殑鍝嶅簲寮忕郴缁燂紝濂藉ソ鍑嗗鍚э紒灏忓竻锛氬績涓竾椹鑵锯€︹€?.#涓嬩竴闆嗛鍛婅櫧鐒跺皬甯呭凡缁忛€氳繃浜嗕竴涓潰璇曞畼鐨勫鏍革紝浣嗘槸鐩墠鐨勫搷搴斿紡绯荤粺杩樹笉澶熷畬鍠勶紝杩樻湁寰堝闂銆傛瘮濡傦細宓屽鎵цeffects浼氭湁浠€涔堥棶棰橈紵浼氫笉浼氬嚭鐜板惊鐜緷璧栥€佹寰幆绛夐棶棰橈紵鈥︹€﹁鐪嬩簩闈㈠皬甯呮槸濡備綍瑙e喅杩欎簺闂鐨勶紝鏁鏈熷緟銆傛渶鍚庯紝甯屾湜鑳戒竴鐩存妸瀹炵敤鐨勩€佸熀纭€鐨勩€佽繘闃剁殑鐭ヨ瘑鐐瑰垎浜粰澶у锛屼竴璧锋棭鐐逛笅鐝紝蹇箰閽撻奔銆傛湡寰呭ぇ瀹跺叧娉ㄦ帢閲戯細鍓嶇榛戝ご楸硷紝涔熷彲浠ュ湪鍏紬鍙凤細鍓嶇榛戝ご楸兼壘鍒版垜銆傚弬鑰僔ue.js璁捐涓庡疄鐜?/p>