Vue Ref全家桶具體用法詳解
1. ref
在Vue3中,ref
成為了一個全家桶,除了用于創(chuàng)建響應式數(shù)據(jù)之外,還可以用于引用DOM元素、組件實例和其他對象。以下是ref
的具體用法:
1.1. 創(chuàng)建響應式數(shù)據(jù)
我們可以使用ref
函數(shù)來創(chuàng)建響應式數(shù)據(jù),例如:
<template> <div>{{ count }}</div> </template> <script setup lang="ts"> import { ref } from 'vue' const count = ref(0) console.log(count.value) // 輸出 0 count.value += 1 console.log(count.value) // 輸出 1 </script> <style scoped> </style>
注意被ref包裝之后需要.value 來進行賦值
在這個例子中,我們使用ref
函數(shù)來創(chuàng)建一個響應式數(shù)據(jù)count
,初始值為0
。我們可以使用count.value
來訪問和修改這個值。
1.2. 引用DOM元素
我們可以使用ref
函數(shù)來引用DOM元素,例如:
<template> <div ref="container"></div> </template> <script setup lang="ts"> import { ref, onMounted } from 'vue' const container = ref(null) // 注意:此處的變量名必須和標簽上的屬性名一致 onMounted(() => { console.log(container.value) // 輸出 <div></div> }) </script> <style scoped> </style>
在這個例子中,我們使用ref
函數(shù)來創(chuàng)建一個container
引用,然后在模板中使用ref="container"
來將這個引用綁定到一個<div>
元素上。在setup
函數(shù)中,我們使用onMounted
鉤子來訪問這個引用的值。
1.3. 引用組件實例
我們可以使用ref
函數(shù)來引用組件實例,例如:
<template> <Child ref="child" /> </template> <script setup lang="ts"> import { ref } from 'vue' import Child from './Child.vue' const child = ref(null) </script> <style scoped> </style>
在這個例子中,我們使用ref
函數(shù)來創(chuàng)建一個child
引用,然后將這個引用綁定到一個<Child>
組件上。在script
中,我們將這個引用暴露出去,以便在其他地方使用。
1.4. 引用其他對象
除了DOM元素和組件實例之外,我們還可以使用ref
函數(shù)來引用其他對象,例如:
<template> <Child ref="child" /> </template> <script setup lang="ts"> import { ref } from 'vue' const data = { name: 'John' } const obj = ref(data) console.log(obj.value.name) // 輸出 'John' obj.value.name = 'Mary' console.log(data.name) // 輸出 'Mary' <script> <style scoped> </style>
在這個例子中,我們使用ref
函數(shù)來引用一個對象data
,然后將這個引用賦值給一個obj
變量。我們可以使用obj.value
來訪問和修改這個對象。在這個例子中,我們將obj.value.name
修改為Mary
,然后發(fā)現(xiàn)data.name
也被修改了。
1.5. ref源碼
在Vue3中,ref函數(shù)的源碼如下:
import { isObject } from '@vue/shared' import { ReactiveFlags, reactive } from './reactive' export function ref(value) { // 如果value已經(jīng)是一個ref對象,直接返回它 if (isRef(value)) { return value } // 創(chuàng)建一個響應式對象 let valueIsObject = isObject(value) const ref = { // 標記這個對象是一個ref對象 [ReactiveFlags.IS_REF]: true, // 獲取ref的值 get value() { // 如果value是一個對象,則返回一個響應式對象 if (valueIsObject) { return reactive(value) } return value }, // 設置ref的值 set value(newVal) { if (valueIsObject) { value = newVal valueIsObject = isObject(newVal) return } // 如果value是一個基本類型的值,則直接修改它 value = newVal } } return ref }
在這個源碼中,ref
函數(shù)首先會判斷傳入的值是否已經(jīng)是一個ref
對象,如果是則直接返回它,否則會創(chuàng)建一個響應式對象來作為ref
對象的值。然后ref
函數(shù)會返回一個擁有value
屬性的對象,當讀取這個屬性時,如果它的值是一個對象,則會返回一個響應式對象,否則直接返回它的值;當修改這個屬性時,如果它的值是一個對象,則會將新值轉化為響應式對象,否則直接修改它的值。
2. isRef
在Vue3中,isRef
函數(shù)用于判斷一個對象是否為ref
對象,它通過判斷這個對象是否擁有一個特殊的屬性IS_REF
來進行判斷。這個特殊屬性的值為true
,表示這個對象是一個ref
對象。
2.1. isRef的使用
<template> <div class="wrapper"></div> </template> <script setup lang="ts"> import { isRef, ref } from 'vue'; const name: string = '張三'; console.log(isRef(name)); // false const age = ref(10); console.log(isRef(age)); // true </script> <style scoped> </style>
2.2. isRef源碼
// 判斷一個對象是否為ref對象 export function isRef(r) { return Boolean(r && r[ReactiveFlags.IS_REF]) }
3. shallowRef
在Vue3中shallowRef
函數(shù),用于創(chuàng)建一個“淺層”的響應式對象。
與ref
函數(shù)不同的是,shallowRef
函數(shù)不會將其值轉化為響應式對象,而是直接將其作為普通的對象或數(shù)組來處理。這意味著,當修改shallowRef
對象的屬性或數(shù)組的元素時,Vue3將不會追蹤這些變化。這種“淺層”的響應式對象對于一些不需要完全響應式的場景非常有用,例如緩存一些數(shù)據(jù)或跟蹤某些狀態(tài)。
3.1. shallowRef的使用
下面是一個使用shallowRef
函數(shù)的示例:
<template> <div>{{ obj.name }}</div> </template> <script setup lang="ts"> import { shallowRef } from 'vue' const obj = { name: 'John', age: 30 } const ref = shallowRef(obj) console.log(ref.value.name) // 輸出 'John' ref.value.name = 'Mary' console.log(obj.name) // 輸出 'Mary' </script> <style scoped> </style>
在這個示例中,我們使用shallowRef
函數(shù)來創(chuàng)建一個“淺層”
的響應式對象ref
,并將其值設置為obj
對象。當我們修改ref.value.name
屬性的值時,obj.name
屬性的值也發(fā)生了改變。這是因為obj
對象和ref
對象共享同一個引用。
3.2. shallowRef的源碼
在Vue3中,shallowRef
函數(shù)的源碼如下:
import { isObject, toRawType } from '@vue/shared' import { track, trigger } from './effect' import { ReactiveFlags } from './reactive' const shallowGet = (value) => value const shallowSet = () => { console.warn( `Value assigned to a shallow ref ${String(value)} is not reactive, ` + `expecting explicitly passing deep: true in ref() options` ) } class ShallowRefImpl { public readonly __v_isRef = true public readonly [ReactiveFlags.IS_SHALLOW] = true constructor(public _value) {} get value() { track(this, 'get', 'value') return this._value } set value(newValue) { if (newValue !== this._value) { this._value = newValue trigger(this, 'set', 'value', newValue) } } } export function shallowRef(value) { return new ShallowRefImpl(value) } export function isShallowRef(value) { return !!value[ReactiveFlags.IS_SHALLOW] }
shallowRef
函數(shù)會創(chuàng)建一個ShallowRefImpl
對象,并將傳入的值作為其內部的_value
屬性的值。ShallowRefImpl
對象是一個帶有get
和set
方法的普通對象,當讀取value
屬性時,get
方法會返回_value
屬性的值;當修改value
屬性時,set
方法會將新值賦值給_value
屬性,并觸發(fā)相應的依賴。
4.triggerRef
強制更新DOM
4.1. triggerRef的使用
triggerRef
的使用非常簡單,只需要傳遞一個Ref
對象作為參數(shù)即可。例如:
import { ref, triggerRef } from 'vue' const count = ref(0) // 在某些情況下需要手動更新count,可以使用triggerRef triggerRef(count)
在這個例子中,我們使用ref
函數(shù)創(chuàng)建了一個名為count
的響應式引用,它的初始值為0
。然后我們在某些情況下需要手動更新count,這時我們可以使用triggerRef
函數(shù)來觸發(fā)它的更新。
需要注意的是,當使用triggerRef
函數(shù)觸發(fā)更新時,它只會更新Ref
對象本身,而不會更新與之相關聯(lián)的組件。因此,我們應該在明確知道需要手動更新時使用triggerRef
函數(shù),而在普通情況下使用Vue
自身的響應式系統(tǒng)來自動更新相關組件。
4.2. triggerRef的源碼實現(xiàn)
在Vue3中,triggerRef
函數(shù)用于觸發(fā)一個ref
對象的依賴更新。其源碼如下:
import { effect } from './effect' import { track, trigger } from './operations' export function triggerRef(ref) { if (ref.__v_isRef) { const value = ref.value if (isTracking()) { track(ref, 'set', 'value') } ref.value = value trigger(ref, 'set', 'value', value) } else { console.warn(`triggerRef() expects a ref object passed as its argument.`) } }
在這個源碼中,首先判斷傳入的對象是否為ref
對象,如果是則獲取它的值,并使用track
函數(shù)追蹤這個ref
對象的依賴。然后將這個ref
對象的值賦值給它自己的value
屬性,并使用trigger
函數(shù)觸發(fā)這個ref
對象的依賴更新。如果傳入的對象不是ref
對象,則會輸出一個警告信息。
5. customRef
在 Vue 3 中,提供了一個 customRef
函數(shù),用于創(chuàng)建一個自定義的、可響應的引用對象。與 ref
和 shallowRef
不同的是,customRef
可以自定義 get
和 set
方法的實現(xiàn)邏輯,從而實現(xiàn)更加靈活的響應式行為。
使用 customRef
函數(shù)創(chuàng)建的引用對象與 ref
對象類似,也具有 value
屬性,當讀取這個屬性時,會觸發(fā) get
方法的執(zhí)行;當修改這個屬性時,會觸發(fā) set
方法的執(zhí)行,并且會觸發(fā)相應的依賴更新。與 ref
對象不同的是,customRef
函數(shù)本身并不會對傳入的初始值進行處理,而是將其直接作為 get
方法的返回值,需要自己手動處理。
下面是 customRef
函數(shù)的使用示例:
5.1. customRef使用
import { customRef } from 'vue' const myRef = customRef((track, trigger) => ({ value: 0, get() { track() return this.value }, set(newValue) { this.value = newValue trigger() } })) console.log(myRef.value) // 輸出 0 myRef.value = 1 console.log(myRef.value) // 輸出 1
在這個示例中,使用 customRef
函數(shù)創(chuàng)建了一個自定義的引用對象 myRef
,它的 get
方法用于追蹤依賴,返回 value
屬性的值;set
方法用于修改 value
屬性的值,并觸發(fā)相應的依賴更新。當讀取和修改 myRef
對象的 value
屬性時,會分別觸發(fā)它的 get
和 set
方法。
注意:customRef
函數(shù)的參數(shù)是一個函數(shù),這個函數(shù)接收兩個參數(shù),分別是 track
和 trigger
函數(shù),它們用于追蹤依賴和觸發(fā)依賴更新。
5.2. customRef 函數(shù)的源代碼
import { track, trigger } from './effect' export function customRef(factory) { const ref = { __v_isRef: true, get value() { return factory().get() }, set value(newValue) { factory().set(newValue) } } return ref } export function triggerRef(ref) { trigger(ref, 'set', 'value', ref.value) }
在這個源碼中,定義了一個 customRef
函數(shù),它接收一個工廠函數(shù)作為參數(shù),用于創(chuàng)建一個自定義的引用對象。在函數(shù)內部,創(chuàng)建了一個普通的對象 ref
,它有一個只讀的 __v_isRef
屬性,用于標識它是一個 ref
對象;還有一個名為 value
的屬性,用于存儲引用對象的值,并且在讀取和修改時會觸發(fā)工廠函數(shù)的 get
和 set
方法。在 customRef
函數(shù)的最后,返回這個 ref
對象。
總結:這篇文章介紹了Vue3中的ref
函數(shù)、isRef
函數(shù)、shallowRef
函數(shù)和customRef
函數(shù)。ref
函數(shù)主要用于創(chuàng)建響應式對象,引用DOM
實例,引用組件實例等。isRef
函數(shù)主要用于判斷傳入的數(shù)據(jù)是不是響應式對象。shallowRef
函數(shù)創(chuàng)建一個“淺層”的響應式對象,只追蹤值的屬性變化,而不追蹤對象內部屬性的變化。customRef
函數(shù)可以創(chuàng)建自定義的引用對象,可以自定義get
和set
方法的實現(xiàn)邏輯。此外,文章還介紹了triggerRef
函數(shù),用于觸發(fā)ref
對象的依賴更新。
到此這篇關于Vue Ref全家桶具體用法詳解的文章就介紹到這了,更多相關Vue Ref內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue?router權限管理實現(xiàn)不同角色顯示不同路由
本文主要介紹了vue?router權限管理實現(xiàn)不同角色顯示不同路由,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03使用 Vue-TCB 快速在 Vue 應用中接入云開發(fā)的方法
這篇文章主要介紹了如何使用 Vue-TCB 快速在 Vue 應用中接入云開發(fā),本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02在vue項目中promise解決回調地獄和并發(fā)請求的問題
這篇文章主要介紹了在vue項目中promise解決回調地獄和并發(fā)請求的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11