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

带你全方位掌握ref和reactive,开启Vue3响应式的大门!

时间:2023-03-31 22:15:02 vue.js

涓嶇煡閬撳ぇ瀹跺湪浣跨敤Vue3鐨勬椂鍊欐湁娌℃湁杩欐牱鐨勭枒鎯戯紝鈥渞ef鍜宺ective閮藉彲浠モ€嬧€嬪垱寤哄搷搴斿紡瀵硅薄锛屾垜搴旇鎬庝箞閫夋嫨锛熲€濓紝鈥滀负浠€涔坮eactive瀵硅薄鍦ㄨВ鏋勪箣鍚庡氨澶卞幓浜嗗搷搴斿紡锛熸垜搴旇鎬庝箞澶勭悊锛熲€濅粖澶╂垜浠氨鏉ュ叏闈㈢洏鐐逛竴涓媟ef鍜宺eactive锛岀浉淇$湅瀹屾墍鏈夊搷搴斿紡鐨勯棶棰橀兘浼氳繋鍒冭€岃В锛屼竴璧锋潵瀛︿範鍚э紒reactive()鐨勫熀鏈敤娉曞湪Vue3涓紝鎴戜滑鍙互浣跨敤reactive()鍒涘缓鍝嶅簲寮忓璞℃垨鏁扮粍锛歩mport{reactive}from'vue'conststate=reactive({count:0})杩欎釜鍝嶅簲寮忓璞″叾瀹炲氨鏄竴涓狿roxy锛屽綋杩欎釜Proxy鐨勫睘鎬ф槸璁块棶锛屽苟鍦ㄤ慨鏀瑰睘鎬ф椂瑙﹀彂鍓綔鐢ㄣ€傝鍦ㄧ粍浠舵ā鏉夸腑浣跨敤鍙嶅簲鐘舵€侊紝闇€瑕佸湪setup()鍑芥暟涓畾涔夊拰杩斿洖銆?script>import{reactive}from'vue'exportdefault{setup(){conststate=reactive({count:0})return{state}}}褰撶劧浣犱篃鍙互浣跨敤鍝嶅簲寮忎唬鐞唙s鍘熷瀵硅薄reactive()杩斿洖鍘熷瀵硅薄鐨凱roxy锛屽畠浠笉鐩哥瓑锛歝onstraw={}constproxy=reactive(raw)console.log(proxy===raw)//false鍘熷瀵硅薄鍦ㄥ畠涔熷彲浠ュ湪妯℃澘涓娇鐢紝浣嗕慨鏀瑰師濮嬪璞′笉浼氳Е鍙戞洿鏂般€傚洜姝わ紝瑕佷娇鐢╒ue鐨勫搷搴斿紡绯荤粺锛屽氨蹇呴』浣跨敤浠g悊銆?scriptsetup>conststate={count:0}functionadd(){state.count++}涓轰簡淇濊瘉璁块棶浠g悊鐨勪竴鑷存€э紝鍦ㄥ悓涓€涓師濮嬪璞′笂璋冪敤reactive()锛屾€绘槸浼氳繑鍥炲悓涓€涓唬鐞嗗璞★紝鑰屼竴涓凡缁忓瓨鍦ㄧ殑浠g悊璋冪敤reactive()鐨勫璞″皢杩斿洖鑷韩锛歝onstraw={}constproxy1=reactive(raw)constproxy2=reactive(raw)console.log(proxy1===proxy2)//trueconsole.log(reactive(proxy1)===proxy1)//true姝よ鍒欎篃閫傜敤浜庡祵濂楀璞°€備緷璧栨繁搴﹀搷搴旓紝鍝嶅簲瀵硅薄涓殑宓屽瀵硅薄浠嶇劧鏄竴涓唬鐞嗭細constraw={}constproxy=reactive({nested:raw})constnested=reactive(raw)console.log(proxy.nested===nested)//trueshallowReactive()鍦╒ue涓紝鐘舵€侀粯璁ゆ槸娣卞害鍝嶅簲鐨勩€備絾鍦ㄦ煇浜涘満鏅笅锛屾垜浠彲鑳藉笇鏈涘垱寤轰竴涓祬灞傜殑鍙嶅簲瀵硅薄锛屼娇鍏跺彧鍦ㄩ《灞傚搷搴旓紝杩欐椂鎴戜滑鍙互浣跨敤shallowReactive()銆俢onststate=shallowReactive({foo:1,nested:{bar:2}})//鐘舵€佹湰韬殑灞炴€ф槸鍙嶅簲鎬х殑state.foo++//搴曞眰宓屽瀵硅薄涓嶆槸鍙嶅簲鎬х殑锛屼笉浼氭寜棰勬湡鐘舵€佸伐浣溿€俷ested.bar++娉ㄦ剰锛氭祬鍙嶅簲瀵硅薄搴旇鍙敤浜庣粍浠朵腑鐨勬牴绾х姸鎬併€傞伩鍏嶅皢鍏跺祵濂楀湪鍙嶅簲瀵硅薄鍐呴儴锛屽洜涓哄叾鍐呴儴鐨勫睘鎬у叿鏈変笉涓€鑷寸殑鍙嶅簲琛屼负锛屽祵濂楀悗灏嗛毦浠ョ悊瑙e拰璋冭瘯銆俽eactive()鐨勫眬闄愭€eactive()铏界劧寮哄ぇ锛屼絾涔熸湁浠ヤ笅灞€闄愭€э細1銆佸彧瀵瑰璞$被鍨嬶紙瀵硅薄銆佹暟缁勩€丮ap銆丼et绛夐泦鍚堢被鍨嬶級鏈夋晥锛岃€屽師濮嬬被鍨嬪string銆乶umber,鍜宐oolean绫诲瀷鏃犳晥銆?.鍥犱负Vue鐨勫弽搴旂郴缁熸槸閫氳繃灞炴€ц闂潵璺熻釜鐨勶紝濡傛灉鎴戜滑鐩存帴鈥滄浛鎹⑩€濅竴涓弽搴斿璞★紝杩欏皢瀵艰嚧涓庡垵濮嬪紩鐢ㄧ殑鍙嶅簲杩炴帴涓㈠け锛?scriptsetup>import{reactive}from'vue'letstate=reactive({count:0})functionchange(){//闈炲弽搴旀€ф浛鎹tate=reactive({count:1})}3.灏嗗搷搴斿璞$殑灞炴€ц祴鍊兼垨瑙f瀯缁欏眬閮ㄥ彉閲忥紝鎴栬€呭睘鎬т紶鍏ュ嚱鏁版椂锛屼細澶卞幓鍝嶅簲鎬э細conststate=reactive({count:0})//n涓哄眬閮ㄥ彉閲忥紝state.count澶卞幓鍝嶅簲鎬ц繛鎺etn=state.count//does涓嶅奖鍝嶇姸鎬乶++//count涔熷け鍘讳簡涓巗tate.count鐨勫搷搴旇繛鎺et{count}=state//涓嶅奖鍝嶇姸鎬乧ount++//鍙傛暟count涔熷け鍘讳簡涓巗tate.count鐨勫搷搴旇繛鎺state.countfunctioncallSomeFunction(count){//涓嶄細褰卞搷statecount++}callSomeFunction(state.count)涓轰簡瑙e喅涓婇潰鐨勯檺鍒讹紝ref鐧诲満浜嗭紒ref()Vue鎻愪緵浜嗕竴涓猺ef()鏂规硶锛屽厑璁告垜浠娇鐢ㄤ换浣曞€肩被鍨嬪垱寤哄搷搴斿紡寮曠敤銆傚熀鏈敤娉時ef()灏嗕紶鍏ョ殑鍙傛暟鍖呰鍒板叿鏈塿alue灞炴€х殑ref瀵硅薄涓細import{ref}from'vue'constcount=ref(0)console.log(count)//{value:0}count.value++console.log(count.value)//1鍜屽搷搴斿紡瀵硅薄鐨勫睘鎬х被浼硷紝ref鐨剉alue灞炴€т篃鏄搷搴斿紡鐨勩€傚悓鏃讹紝褰撳€兼槸瀵硅薄绫诲瀷鏃讹紝Vue浼氳嚜鍔ㄤ娇鐢╮eactive()鏉ュ鐞嗚繖涓€笺€傚寘鍚璞$殑ref鍙互鍙嶅簲鎬у湴鏇挎崲鏁翠釜瀵硅薄锛?scriptsetup>import{ref}from'vue'letstate=ref({count:0})functionchange(){//杩欐槸鍙嶅簲鎬ф浛鎹㈢姸鎬併€倂alue=ref({count:1})}ref浠庝竴鑸璞¤В鏋勫睘鎬ф垨灏嗗睘鎬т紶閫掔粰鍑芥暟鏃讹紝涓嶄細鏈夊搷搴旀€х殑鎹熷け锛歝onststate={count:ref(0)}//瑙f瀯鍚?andstate.count浠嶇劧淇濇寔鍝嶅簲杩炴帴const{count}=state//浼氬奖鍝峴tatecount.value++//杩欎釜鍑芥暟鎺ユ敹涓€涓猺ef锛屼紶鍏ョ殑鍊间粛鐒朵繚鎸佸搷搴旇繛鎺unctioncallSomeFunction(count){//浼氬奖鍝嶇姸鎬佽鏁般€倂alue++}callSomeFunction(state.count)ref()鍏佽鎴戜滑浣跨敤浠讳綍鍊肩被鍨嬪垱寤簉ef瀵硅薄骞朵紶閫掑畠浠€屼笉浼氬け鍘诲弽搴旀€с€傛鍔熻兘闈炲父閲嶈锛岀粡甯哥敤浜庡皢閫昏緫鎻愬彇鍒板鍚堚€嬧€嬪嚱鏁颁腑銆?/mouse.jsexportfunctionuseMouse(){constx=ref(0)consty=ref(0)//...return{x,y}}ref鐨勬媶鍖呮墍璋撴媶鍖呭氨鏄幏鍙杛ef瀵硅薄涓婄殑value灞炴€х殑鍊笺€備袱涓父鐢ㄧ殑鏂规硶鏄?value鍜寀nref()銆倁nref()鏄疺ue鎻愪緵鐨勪竴涓柟娉曘€傚鏋滃弬鏁版槸ref锛屽垯杩斿洖value灞炴€х殑鍊硷紝鍚﹀垯杩斿洖鍙傛暟鏈韩銆傚湪妯℃澘涓睍寮€refs褰搑efs鍦ㄦā鏉夸腑浣滀负椤剁骇灞炴€ц闂椂锛屽畠浠細鑷姩灞曞紑锛屾棤闇€浣跨敤.value銆傝繖鏄墠闈㈢殑渚嬪瓙锛屼娇鐢╮ef()浠f浛锛?scriptsetup>import{ref}from'vue'constcount=ref(0)杩樻湁涓€绉嶆儏鍐碉紝濡傛灉鏂囨湰鎻掑€?{{}})璁$畻鐨勬渶缁堝€兼槸ref锛屼篃浼氳嚜鍔ㄥ睍寮€銆備互涓嬮潪椤剁骇灞炴€у皢琚纭憟鐜般€?scriptsetup>import{ref}from'vue'constobject={foo:ref(1)}鍏朵粬鎯呭喌涓嶄細鑷姩瑙e寘锛屽锛歰bject.foo涓嶆槸椤剁骇灞炴€э紝鏂囨湰鎻掑€?{{}})璁$畻鐨勬渶缁堝€间笉鏄痳ef:constobject={foo:ref(1)}浠ヤ笅灏嗕笉浼氭寜棰勬湡宸ヤ綔锛?div>{{object.foo+1}}

灏嗗憟鐜癧objectObject]1鍥犱负object.foo鏄竴涓猺ef瀵硅薄銆傛垜浠彲浠ラ€氳繃浣縡oo鎴愪负椤剁骇灞炴€ф潵瑙e喅杩欎釜闂锛歝onstobject={foo:ref(1)}const{foo}=object
{{foo+1}}
鐜板湪缁撴灉灏嗘槸姝g‘鐨勫憟鐜板嚭鏉ャ€傚湪鍙嶅簲寮忓璞′腑灞曞紑寮曠敤褰搑ef宓屽鍦ㄥ弽搴斿紡瀵硅薄涓苟浣滀负灞炴€ц闂垨鏇存敼鏃讹紝瀹冧細鑷姩灞曞紑锛屽洜姝ゅ畠鐨勮涓哄氨鍍忎竴涓櫘閫氬睘鎬э細constcount=ref(0)conststate=reactive({count})console.log(state.count)//0state.count=1console.log(state.count)//1浠呭綋宓屽鍦ㄦ繁搴﹀弽搴斿璞′腑鏃讹紝鎵嶄細杩涜瑙e寘銆傚綋ref浣滀负娴呭弽搴斿璞$殑灞炴€ц闂椂锛屽畠涓嶄細琚В鍖咃細constcount=ref(0)conststate=shallowReactive({count})console.log(state.count)//{value:0}鑰屼笉鏄?锛屽鏋滃皢鏂扮殑ref鍒嗛厤缁欎笌ref鍏宠仈鐨勫睘鎬э紝閭d箞瀹冨皢鏇挎崲鏃х殑ref锛歝onstcount=ref(1)conststate=reactive({count})constotherCount=ref(2)state.count=otherCountconsole.log(state.count)//2//count姝ゆ椂宸茬粡鍜宻tate.count澶卞幓鑱旂郴console.log(count.value)//1ref鏁扮粍鍜岄泦鍚堢被鍨嬩腑瀵硅薄鐨勮В鍖呭拰鍝嶅簲涓嶅悓锛屽綋ref浣滀负鍙嶅簲鏁扮粍鐨勫厓绱犳垨鏈湴闆嗗悎绫诲瀷锛堝Map锛夎闂椂锛屼笉浼氭墽琛岃В鍖呫€俢onstbooks=reactive([ref('Vue3Guide')])//闇€瑕?valueconsole.log(books[0].value)constmap=reactive(newMap([['count',ref(0)]]))//杩欓噷闇€瑕?valueconsole.log(map.get('count').value)toRef()toRef鏄竴绉嶆牴鎹搷搴斿璞′笂鐨勫睘鎬у垱寤哄搴攔ef鐨勬柟娉曘€傝繖鏍峰垱寤虹殑ref涓庡叾source灞炴€т繚鎸佸悓姝ワ細鏇存敼source灞炴€х殑鍊煎皢鏇存柊ref鐨勫€硷紝鍙嶄箣浜︾劧銆俢onststate=reactive({foo:1,bar:2})constfooRef=toRef(state,'foo')//鏀瑰彉婧愬睘鎬ф洿鏂皉efstate.foo++console.log(fooRef.value)//2//鏇存敼ref涔熶細鏇存柊婧愬睘鎬ooRef.value++console.log(state.foo)//3toRef()褰撲綘鎯冲皢prop鐨剅ef浼犻€掔粰澶嶅悎鍑芥暟鏃跺緢鏈夌敤锛?scriptsetup>import{toRef}from'vue'constprops=defineProps(/*...*/)//灏哷props.foo`杞崲涓簉ef锛岀劧鍚庝紶鍏ョ粍鍚堝嚱鏁皍seSomeFeature(toRef(props,'foo'))褰搕oRef涓庣粍浠秔rops缁撳悎浣跨敤鏃讹紝瀵筽rops杩涜鏇存敼鐨勯檺鍒朵粛鐒舵湁鏁堛€傚鏋滃皢鏂板€间紶閫掔粰ref绛夊悓浜庡皾璇曠洿鎺ユ敼鍙榩rops锛岃繖鏄笉鍏佽鐨勩€傚湪杩欑鎯呭喌涓嬶紝鎮ㄥ彲浠ヨ€冭檻浣跨敤computedwithget鍜宻et浠f浛銆傛敞鎰忥細鍗充娇婧愬睘鎬у綋鍓嶄笉瀛樺湪锛宼oRef()涔熶細杩斿洖涓€涓彲鐢ㄧ殑寮曠敤銆傝繖浣垮緱瀹冨湪澶勭悊鍙€夐亾鍏锋椂寰堟湁鐢紝鑰宼oRefs涓嶄細涓哄彲閫夐亾鍏峰垱寤虹浉搴旂殑寮曠敤銆傝鎴戜滑鐪嬬湅涓嬮潰鐨則oRefs銆倀oRefs()toRefs()鏄竴绉嶅皢鍝嶅簲寮忓璞′笂鐨勬墍鏈夊睘鎬ц浆鎹负refs锛岀劧鍚庡皢杩欎簺refs缁勫悎鎴愪竴涓叕鍏卞璞$殑鏂规硶銆傛鍏叡瀵硅薄鐨勬瘡涓睘鎬ч兘涓庢簮瀵硅薄鐨勫睘鎬т繚鎸佸悓姝ャ€俢onststate=reactive({foo:1,bar:2})//鐩稿綋浜?/conststateAsRefs={//foo:toRef(state,'foo'),//bar:toRef(state,'bar')//}conststateAsRefs=toRefs(state)state.foo++console.log(stateAsRefs.foo.value)//2stateAsRefs.foo.value++console.log(state.foo)//3鏉ヨ嚜缁勫悎鍑芥暟toRefs鍦ㄨ繑鍥炲弽搴斿璞℃椂寰堟湁鐢ㄣ€傚畠鍏佽鎴戜滑鍦ㄤ笉鎹熷け鍝嶅簲鎬х殑鎯呭喌涓嬭В鏋勮繑鍥炵殑瀵硅薄锛?/feature.jsexportfunctionuseFeature(){conststate=reactive({foo:1,bar:2})//...//灏嗚繑鍥炵殑鎵€鏈夊睘鎬ч兘杞崲torefreturntoRefs(state)}toRefs鍙細鍒涘缓婧愬璞′笂宸插瓨鍦ㄧ殑灞炴€х殑寮曠敤銆傚鏋滀綘鎯充负涓€涓繕涓嶅瓨鍦ㄧ殑灞炴€у垱寤轰竴涓猺ef锛屼綘闇€瑕佷娇鐢ㄤ笂闈㈡彁鍒扮殑toRef銆備互涓婂氨鏄痳ef鍜宺eactive鐨勮缁嗙敤娉曘€備笉鐭ラ亾澶у鏈夋病鏈夋柊鐨勬敹鑾枫€傛帴涓嬫潵锛岃鎴戜滑璁ㄨ鍝嶅簲鎬у師鍒欍€傚搷搴斿紡鍘熺悊Vue2鐨勯檺鍒舵垜浠兘鐭ラ亾Vue2涓殑鍝嶅簲寮忎娇鐢∣bject.defineProperty()閫氳繃getter/setter鏉ユ嫤鎴睘鎬с€傝繖绉嶆柟寮忓鑰佺増鏈祻瑙堝櫒鐨勬敮鎸佹瘮杈冨弸濂斤紝浣嗘槸涔熸湁寰堝缂虹偣锛氬垵濮嬪寲鏃跺彧浼氬宸叉湁鐨勫璞″睘鎬ц繘琛屽搷搴斿紡澶勭悊銆備篃灏辨槸璇达紝鍦ㄦ坊鍔犳垨鍒犻櫎灞炴€ф椂锛孷ue鏃犳硶瀵瑰叾杩涜鐩戞帶銆傚繀椤讳娇鐢ㄧ壒娈婄殑API鏉ュ鐞嗐€傝鏁扮粍鏄€氳繃瑕嗙洊鍘熷瀷瀵硅薄涓婄殑7涓柟娉曟潵瀹炵幇鐨勩€傚鏋滈€氳繃涓嬫爣淇敼浜嗘暟鎹紝Vue涔熸槸鏃犳剰璇嗙殑銆傝繕浣跨敤鐗规畩鐨凙PI澶勭悊銆傛棤娉曞鐞哅ap銆丼et绛夐泦鍚堢被鍨嬨€傚叿鏈夊弽搴旂姸鎬佺殑閫昏緫涓嶅鏄撻噸鐢ㄣ€俈ue3鐨勫搷搴斿紡绯荤粺閽堝浠ヤ笂鎯呭喌锛孷ue3鐨勫搷搴斿紡绯荤粺璇炵敓浜嗭紒Vue3浣跨敤Proxy鍒涘缓鍝嶅簲寮忓璞★紝ref鍙娇鐢╣etter/setter锛屽畬缇庤В鍐充簡涓婅堪闄愬埗銆備笅闈㈢殑浠g爜鍙互璇存槑瀹冧滑鏄浣曞伐浣滅殑锛歿target[key]=valuetrigger(target,key)}})}functionref(value){constrefObject={getvalue(){track(refObject,'value')杩斿洖鍊紏,setvalue(newValue){value=newValuetrigger(refObject,'value')}}returnrefObject}涓嶉毦鐪嬪嚭锛屽綋灏嗗搷搴斿璞$殑灞炴€цВ鏋勪负灞€閮ㄥ彉閲忔椂锛屽搷搴旀€т細鈥滄柇寮€杩炴帴鈥濄€傚洜涓鸿闂眬閮ㄥ彉閲忎笉浼氳Е鍙慻et/set浠g悊鎹曡幏銆傝鎴戜滑鍥炲埌鍝嶅簲鍘熷垯銆傚湪track()鍐呴儴锛屾垜浠鏌ュ綋鍓嶆槸鍚︽湁浠讳綍鍓綔鐢ㄦ鍦ㄨ繍琛屻€傚鏋滄湁锛屽畠浼氭壘鍒板瓨鍌ㄦ墍鏈夎窡韪灞炴€х殑璁㈤槄鑰呯殑Set锛岀劧鍚庡皢褰撳墠鍓綔鐢ㄤ綔涓烘柊鐨勮闃呰€呮坊鍔犲埌璇et涓€?/activeEffect灏嗗湪鍓綔鐢ㄥ嵆灏嗚繍琛屼箣鍓嶈缃瓨鍌ㄥ湪涓€涓叏灞€鐨刉eakMap>>鏁版嵁缁撴瀯涓€傚鏋滃湪绗竴娆¤窡韪椂娌℃湁鎵惧埌鐩稿簲灞炴€ц闃呯殑鍓綔鐢ㄩ泦鍚堬紝鍒欎細鍦ㄦ澶勫垱寤恒€傝繖灏辨槸getSubscribersForProperty()鍑芥暟鐨勪綔鐢ㄣ€傚湪trigger()涓紝鎴戜滑鍐嶆鎵惧埌璇ュ睘鎬х殑鎵€鏈夎闃呭壇浣滅敤銆傝繖娆℃垜浠叏閮ㄦ墽琛岋細functiontrigger(target,key){consteffects=getSubscribersForProperty(target,key)effects.forEach((effect)=>effect())}杩欎簺鍓綔鐢ㄧ敤浜庢墽琛宒iff绠楁硶鏇存柊鐨勯〉闈€傝繖鏄搷搴斿紡绯荤粺鐨勪竴鑸師鐞嗐€俈ue3杩樹紭鍖栦簡缂栬瘧鍣紝浼樺寲浜哾iff绠楁硶绛夌瓑銆備笉寰椾笉浣╂湇娓歌揪锛屼粬鎶奦ue鐨勫搷搴斿紡绯荤粺鎻愬崌浜嗕竴涓眰娆★紒濂戒簡锛屼粖澶╃殑鍒嗕韩灏卞埌杩欓噷銆備笉鐭ラ亾澶у瀵箁ef鍜宺eactive鏈夋病鏈夋洿娣卞叆鐨勭悊瑙c€傛杩庡湪璇勮鍖虹暀瑷€銆傛湁涓€鐐规劅瑙﹁寰楃偣璧炴敮鎸佸摝锛侌煉曞弬鑰冩枃妗o細Vue3瀹樼綉