響應性 API:核心
ref()
接收一個內部值並返回一個響應性和可變的 ref 物件,該物件具有一個指向內部值的單屬性 .value
。
型別
tsfunction ref<T>(value: T): Ref<UnwrapRef<T>> interface Ref<T> { value: T }
詳情
ref 物件是可變的 - 即您可以分配新的值給
.value
。它也是響應性的 - 即對.value
的任何讀取操作都會被跟蹤,寫入操作將觸發相關效果。如果將物件分配為 ref 的值,則物件會透過 reactive() 被轉換為深度響應性。這也意味著如果物件包含巢狀的 ref,它們將被深度展開。
為了避免深度轉換,請使用
shallowRef()
。示例
jsconst count = ref(0) console.log(count.value) // 0 count.value = 1 console.log(count.value) // 1
另請參閱
computed()
接收一個 getter 函式 並返回一個只讀響應性 ref 物件,該物件包含從 getter 返回的值。它還可以接收一個具有 get
和 set
函式的物件來建立可寫的 ref 物件。
型別
ts// read-only function computed<T>( getter: (oldValue: T | undefined) => T, // see "Computed Debugging" link below debuggerOptions?: DebuggerOptions ): Readonly<Ref<Readonly<T>>> // writable function computed<T>( options: { get: (oldValue: T | undefined) => T set: (value: T) => void }, debuggerOptions?: DebuggerOptions ): Ref<T>
示例
建立只讀計算 ref
jsconst count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // error
建立可寫計算 ref
jsconst count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0
除錯
jsconst plusOne = computed(() => count.value + 1, { onTrack(e) { debugger }, onTrigger(e) { debugger } })
另請參閱
reactive()
返回物件的響應式代理。
型別
tsfunction reactive<T extends object>(target: T): UnwrapNestedRefs<T>
詳情
響應式轉換是“深層”的:它影響所有巢狀屬性。響應式物件在保持響應性的同時,也會深度展開任何引用屬性。
需要注意的是,當引用作為響應式陣列或原生集合型別(如
Map
)的元素訪問時,不會執行引用展開。為了避免深度轉換並僅在根級別保留響應性,請使用shallowReactive()。
返回的物件及其巢狀物件被ES Proxy包裝,並且與原始物件不等價。建議僅使用響應式代理並避免依賴於原始物件。
示例
建立響應式物件
jsconst obj = reactive({ count: 0 }) obj.count++
引用展開
tsconst count = ref(1) const obj = reactive({ count }) // ref will be unwrapped console.log(obj.count === count.value) // true // it will update `obj.count` count.value++ console.log(count.value) // 2 console.log(obj.count) // 2 // it will also update `count` ref obj.count++ console.log(obj.count) // 3 console.log(count.value) // 3
請注意,當引用作為陣列或集合元素訪問時,引用不會被展開
jsconst books = reactive([ref('Vue 3 Guide')]) // need .value here console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // need .value here console.log(map.get('count').value)
當將引用賦值給
reactive
屬性時,該引用也將自動展開tsconst count = ref(1) const obj = reactive({}) obj.count = count console.log(obj.count) // 1 console.log(obj.count === count.value) // true
另請參閱
readonly()
接受一個物件(響應式或純物件)或一個引用,並返回對原始物件的只讀代理。
型別
tsfunction readonly<T extends object>( target: T ): DeepReadonly<UnwrapNestedRefs<T>>
詳情
只讀代理是深層的:訪問的任何巢狀屬性也將是隻讀的。它還具有與
reactive()
相同的引用展開行為,除了展開的值也將變為只讀。為了避免深度轉換,請使用shallowReadonly()。
示例
jsconst original = reactive({ count: 0 }) const copy = readonly(original) watchEffect(() => { // works for reactivity tracking console.log(copy.count) }) // mutating original will trigger watchers relying on the copy original.count++ // mutating the copy will fail and result in a warning copy.count++ // warning!
watchEffect()
立即執行一個函式,同時響應式地跟蹤其依賴項,並在依賴項更改時重新執行它。
型別
tsfunction watchEffect( effect: (onCleanup: OnCleanup) => void, options?: WatchEffectOptions ): WatchHandle type OnCleanup = (cleanupFn: () => void) => void interface WatchEffectOptions { flush?: 'pre' | 'post' | 'sync' // default: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void } interface WatchHandle { (): void // callable, same as `stop` pause: () => void resume: () => void stop: () => void }
詳情
第一個引數是要執行的效應函式。效應函式接收一個函式,可用於註冊清理回撥。清理回撥將在下一次效應重新執行之前被呼叫,並可用於清理無效的副作用,例如掛起的非同步請求(見以下示例)。
第二個引數是一個可選的選項物件,可用於調整效應的重新整理時間或除錯效應的依賴項。
預設情況下,觀察者將在元件渲染之前執行。將
flush: 'post'
設定為將觀察者推遲到元件渲染之後。有關更多資訊,請參閱回撥重新整理時間。在罕見的情況下,可能需要在響應式依賴項更改時立即觸發觀察者,例如,以使快取無效。這可以透過使用flush: 'sync'
來實現。然而,此設定應謹慎使用,因為它可能導致在同時更新多個屬性時出現效能和資料一致性方面的問題。返回值是一個處理函式,可以呼叫它以停止效應再次執行。
示例
jsconst count = ref(0) watchEffect(() => console.log(count.value)) // -> logs 0 count.value++ // -> logs 1
停止觀察者
jsconst stop = watchEffect(() => {}) // when the watcher is no longer needed: stop()
暫停/恢復觀察者:
jsconst { stop, pause, resume } = watchEffect(() => {}) // temporarily pause the watcher pause() // resume later resume() // stop stop()
副作用清理
jswatchEffect(async (onCleanup) => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onCleanup(cancel) data.value = await response })
3.5+中的副作用清理
jsimport { onWatcherCleanup } from 'vue' watchEffect(async () => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onWatcherCleanup(cancel) data.value = await response })
選項
jswatchEffect(() => {}, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })
另請參閱
watchPostEffect()
watchEffect()
的別名,帶有flush: 'post'
選項。
watchSyncEffect()
watchEffect()
的別名,帶有flush: 'sync'
選項。
watch()
觀察一個或多個響應式資料來源,並在資料來源更改時呼叫回撥函式。
型別
ts// watching single source function watch<T>( source: WatchSource<T>, callback: WatchCallback<T>, options?: WatchOptions ): WatchHandle // watching multiple sources function watch<T>( sources: WatchSource<T>[], callback: WatchCallback<T[]>, options?: WatchOptions ): WatchHandle type WatchCallback<T> = ( value: T, oldValue: T, onCleanup: (cleanupFn: () => void) => void ) => void type WatchSource<T> = | Ref<T> // ref | (() => T) // getter | (T extends object ? T : never) // reactive object interface WatchOptions extends WatchEffectOptions { immediate?: boolean // default: false deep?: boolean | number // default: false flush?: 'pre' | 'post' | 'sync' // default: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void once?: boolean // default: false (3.4+) } interface WatchHandle { (): void // callable, same as `stop` pause: () => void resume: () => void stop: () => void }
為了可讀性,型別已簡化。
詳情
watch()
預設是懶載入的 - 即只有當被觀察的源發生變化時,回撥才會被呼叫。第一個引數是觀察者的 源。源可以是以下之一
- 一個返回值的 getter 函式
- 一個 ref
- 一個響應式物件
- ...或者以上任意型別的陣列。
第二個引數是在源發生變化時被呼叫的回撥函式。回撥函式接收三個引數:新值、舊值以及一個用於註冊副作用清理回撥函式的函式。清理回撥函式將在下一次副作用重新執行之前被呼叫,可以用來清理無效的副作用,例如掛起的非同步請求。
當觀察多個源時,回撥函式接收包含新/舊值的兩個陣列,這些值對應於源陣列。
第三個可選引數是一個支援以下選項的選項物件
immediate
:在觀察者建立時立即觸發回撥。第一次呼叫時,舊值將是undefined
。deep
:如果源是物件,強制進行深度遍歷,以便在深度突變時觸發回撥。在 3.5+ 中,這也可以是一個表示最大遍歷深度的數字。參見 深度觀察者。flush
:調整回撥的重新整理時間。參見 回撥重新整理時間 和watchEffect()
。onTrack / onTrigger
:除錯觀察者的依賴關係。參見 觀察者除錯。once
:(3.4+)只執行一次回撥。第一次回撥執行後,觀察者將自動停止。
與
watchEffect()
相比,watch()
允許我們- 懶載入副作用;
- 更具體地指定哪些狀態應該觸發觀察者重新執行;
- 訪問被觀察狀態的當前值和舊值。
示例
觀察 getter
jsconst state = reactive({ count: 0 }) watch( () => state.count, (count, prevCount) => { /* ... */ } )
觀察 ref
jsconst count = ref(0) watch(count, (count, prevCount) => { /* ... */ })
當觀察多個源時,回撥函式接收包含新/舊值的陣列,這些值對應於源陣列
jswatch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { /* ... */ })
當使用 getter 源時,只有當 getter 的返回值發生變化時,觀察者才會觸發。如果您希望在深度突變時觸發回撥,需要顯式地將觀察者強制進入深度模式,使用
{ deep: true }
。注意,在深度模式下,如果回撥是由深度突變觸發的,新值和舊值將是相同的物件jsconst state = reactive({ count: 0 }) watch( () => state, (newValue, oldValue) => { // newValue === oldValue }, { deep: true } )
當直接觀察響應式物件時,觀察者自動處於深度模式
jsconst state = reactive({ count: 0 }) watch(state, () => { /* triggers on deep mutation to state */ })
watch()
與watchEffect()
具有相同的重新整理時間和除錯選項jswatch(source, callback, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })
停止觀察者
jsconst stop = watch(source, callback) // when the watcher is no longer needed: stop()
暫停/恢復觀察者:
jsconst { stop, pause, resume } = watch(() => {}) // temporarily pause the watcher pause() // resume later resume() // stop stop()
副作用清理
jswatch(id, async (newId, oldId, onCleanup) => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onCleanup(cancel) data.value = await response })
3.5+中的副作用清理
jsimport { onWatcherCleanup } from 'vue' watch(id, async (newId) => { const { response, cancel } = doAsyncWork(newId) onWatcherCleanup(cancel) data.value = await response })
另請參閱
onWatcherCleanup()
註冊一個清理函式,在當前觀察者即將重新執行時執行。只能在同步執行 watchEffect
副作用函式或 watch
回撥函式時呼叫(即不能在非同步函式中的 await
語句之後呼叫。)
型別
tsfunction onWatcherCleanup( cleanupFn: () => void, failSilently?: boolean ): void
示例
tsimport { watch, onWatcherCleanup } from 'vue' watch(id, (newId) => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onWatcherCleanup(cancel) })