API de Reactividad: Núcleo
Ver también
Para comprender mejor las API de Reactividad, se recomienda leer los siguientes capítulos de la guía:
- Fundamentos de Reactividad (con la preferencia de API establecida en Composition API)
- Reactividad en Profundidad
ref()
Toma un valor interno y devuelve un objeto ref reactivo y mutable, que tiene una única propiedad .value que apunta al valor interno.
Tipo
tsfunction ref<T>(value: T): Ref<UnwrapRef<T>> interface Ref<T> { value: T }Detalles
El objeto
refes mutable, es decir, puedes asignar nuevos valores a.value. También es reactivo, lo que significa que cualquier operación de lectura a.valuees rastreada y las operaciones de escritura activarán los efectos asociados.Si un objeto se asigna como valor de un
ref, el objeto se convierte en profundamente reactivo con reactive(). Esto también significa que si el objeto contienerefsanidados, estos serán desenvueltos profundamente.Para evitar la conversión profunda, usa
shallowRef()en su lugar.Ejemplo
jsconst count = ref(0) console.log(count.value) // 0 count.value = 1 console.log(count.value) // 1Ver también
computed()
Toma una función getter y devuelve un objeto ref reactivo de solo lectura para el valor devuelto por el getter. También puede tomar un objeto con funciones get y set para crear un objeto ref escribible.
Tipo
ts// solo lectura function computed<T>( getter: (oldValue: T | undefined) => T, // ver enlace "Depuración de computed" a continuación debuggerOptions?: DebuggerOptions ): Readonly<Ref<Readonly<T>>> // escribible function computed<T>( options: { get: (oldValue: T | undefined) => T set: (value: T) => void }, debuggerOptions?: DebuggerOptions ): Ref<T>Ejemplo
Creando un
refcomputed de solo lectura:jsconst count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // errorCreando un
refcomputed escribible:jsconst count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0Depuración:
jsconst plusOne = computed(() => count.value + 1, { onTrack(e) { debugger }, onTrigger(e) { debugger } })Ver también
reactive()
Devuelve un proxy reactivo del objeto.
Tipo
tsfunction reactive<T extends object>(target: T): UnwrapNestedRefs<T>Detalles
La conversión reactiva es "profunda": afecta a todas las propiedades anidadas. Un objeto reactivo también desenvuelve profundamente cualquier propiedad que sea ref mientras mantiene la reactividad.
También debe tenerse en cuenta que no se realiza ninguna envoltura de
refcuando se accede alrefcomo un elemento de un array reactivo o un tipo de colección nativo comoMap.Para evitar la conversión profunda y solo mantener la reactividad a nivel raíz, usa shallowReactive() en su lugar.
El objeto devuelto y sus objetos anidados están envueltos con ES Proxy y no son iguales a los objetos originales. Se recomienda trabajar exclusivamente con el proxy reactivo y evitar depender del objeto original.
Ejemplo
Creando un objeto reactivo:
jsconst obj = reactive({ count: 0 }) obj.count++Desenvuelto de
ref:tsconst count = ref(1) const obj = reactive({ count }) // ref será desenvuelto console.log(obj.count === count.value) // true // actualizará `obj.count` count.value++ console.log(count.value) // 2 console.log(obj.count) // 2 // también actualizará el ref `count` obj.count++ console.log(obj.count) // 3 console.log(count.value) // 3Ten en cuenta que los
refsno se desenvuelven cuando se acceden como elementos de un array o colección:jsconst books = reactive([ref('Vue 3 Guide')]) // necesita .value aquí console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // necesita .value aquí console.log(map.get('count').value)Al asignar un ref a una propiedad
reactive, esereftambién se desenvolverá automáticamente:tsconst count = ref(1) const obj = reactive({}) obj.count = count console.log(obj.count) // 1 console.log(obj.count === count.value) // trueVer también
readonly()
Toma un objeto (reactivo o simple) o un ref y devuelve un proxy de solo lectura al original.
Tipo
tsfunction readonly<T extends object>( target: T ): DeepReadonly<UnwrapNestedRefs<T>>Detalles
Un proxy
readonlyes profundo: cualquier propiedad anidada a la que se acceda también será de solo lectura. También tiene el mismo comportamiento de desenvolvimiento derefquereactive(), excepto que los valores desenvueltos también se harán de solo lectura.Para evitar la conversión profunda, usa shallowReadonly() en su lugar.
Ejemplo
jsconst original = reactive({ count: 0 }) const copy = readonly(original) watchEffect(() => { // funciona para el seguimiento de reactividad console.log(copy.count) }) // mutar el original activará watchers que dependen de la copia original.count++ // mutar la copia fallará y resultará en una advertencia copy.count++ // warning!
watchEffect()
Ejecuta una función inmediatamente mientras rastrea reactivamente sus dependencias y la vuelve a ejecutar cada vez que cambian las dependencias.
Tipo
tsfunction watchEffect( effect: (onCleanup: OnCleanup) => void, options?: WatchEffectOptions ): WatchHandle type OnCleanup = (cleanupFn: () => void) => void interface WatchEffectOptions { flush?: 'pre' | 'post' | 'sync' // por defecto: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void } interface WatchHandle { (): void // invocable, igual que `stop` pause: () => void resume: () => void stop: () => void }Detalles
El primer argumento es la función de efecto a ejecutar. La función de efecto recibe una función que se puede usar para registrar una callback de limpieza. La callback de limpieza se llamará justo antes de la próxima vez que se vuelva a ejecutar el efecto, y se puede usar para limpiar efectos secundarios invalidados, por ejemplo, una solicitud asíncrona pendiente (ver ejemplo a continuación).
El segundo argumento es un objeto de opciones opcional que se puede usar para ajustar el momento de ejecución del efecto o para depurar las dependencias del efecto.
Por defecto, los watchers se ejecutarán justo antes del renderizado del componente. Establecer
flush: 'post'pospondrá el watcher hasta después del renderizado del componente. Consulta Momento de Ejecución de Callback para obtener más información. En casos raros, podría ser necesario activar un watcher inmediatamente cuando una dependencia reactiva cambia, por ejemplo, para invalidar una caché. Esto se puede lograr usandoflush: 'sync'. Sin embargo, esta configuración debe usarse con precaución, ya que puede generar problemas de rendimiento y consistencia de datos si se actualizan varias propiedades al mismo tiempo.El valor de retorno es una función de manejo que se puede llamar para evitar que el efecto se ejecute nuevamente.
Ejemplo
jsconst count = ref(0) watchEffect(() => console.log(count.value)) // -> registra 0 count.value++ // -> registra 1Deteniendo el watcher:
jsconst stop = watchEffect(() => {}) // cuando el watcher ya no sea necesario: stop()Pausando / reanudando el watcher:
jsconst { stop, pause, resume } = watchEffect(() => {}) // pausar temporalmente el watcher pause() // reanudar más tarde resume() // detener stop()Limpieza de efectos secundarios:
jswatchEffect(async (onCleanup) => { const { response, cancel } = doAsyncWork(newId) // `cancel` se llamará si `id` cambia, cancelando // la solicitud anterior si aún no se ha completado onCleanup(cancel) data.value = await response })Limpieza de efectos secundarios en 3.5+:
jsimport { onWatcherCleanup } from 'vue' watchEffect(async () => { const { response, cancel } = doAsyncWork(newId) // `cancel` se llamará si `id` cambia, cancelando // la solicitud anterior si aún no se ha completado onWatcherCleanup(cancel) data.value = await response })Opciones:
jswatchEffect(() => {}, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })Ver también
watchPostEffect()
Alias de watchEffect() con la opción flush: 'post'.
watchSyncEffect()
Alias de watchEffect() con la opción flush: 'sync'.
watch()
Observa una o más fuentes de datos reactivas e invoca una función de callback cuando las fuentes cambian.
Tipo
ts// observando una única fuente function watch<T>( source: WatchSource<T>, callback: WatchCallback<T>, options?: WatchOptions ): WatchHandle // observando múltiples fuentes 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) // objeto reactivo interface WatchOptions extends WatchEffectOptions { immediate?: boolean // por defecto: false deep?: boolean | number // por defecto: false flush?: 'pre' | 'post' | 'sync' // por defecto: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void once?: boolean // por defecto: false (3.4+) } interface WatchHandle { (): void // invocable, igual que `stop` pause: () => void resume: () => void stop: () => void }Los tipos se simplifican para facilitar la lectura.
Detalles
watch()es perezoso por defecto, es decir, la callback solo se llama cuando la fuente observada ha cambiado.El primer argumento es la fuente del watcher. La fuente puede ser una de las siguientes:
- Una función getter que devuelve un valor
- Un
ref - Un objeto reactivo
- ...o un array de los anteriores.
El segundo argumento es la callback que se llamará cuando la fuente cambie. La callback recibe tres argumentos: el nuevo valor, el valor antiguo y una función para registrar una callback de limpieza de efectos secundarios. La callback de limpieza se llamará justo antes de la próxima vez que se vuelva a ejecutar el efecto, y se puede usar para limpiar efectos secundarios invalidados, por ejemplo, una solicitud asíncrona pendiente.
Al observar múltiples fuentes, la callback recibe dos arrays que contienen los valores nuevos y antiguos correspondientes al array de fuentes.
El tercer argumento opcional es un objeto de opciones que admite las siguientes:
immediate: dispara la callback inmediatamente al crear el watcher. El valor antiguo seráundefineden la primera llamada.deep: fuerza el recorrido profundo de la fuente si es un objeto, para que la callback se dispare en mutaciones profundas. En 3.5+, esto también puede ser un número que indica la profundidad máxima de recorrido. Ver Watchers Profundos.flush: ajusta el momento de ejecución de la callback. Ver Momento de Ejecución de Callback ywatchEffect().onTrack / onTrigger: depura las dependencias del watcher. Ver Depuración de Watchers.once: (3.4+) ejecuta la callback solo una vez. El watcher se detiene automáticamente después de la primera ejecución de la callback.
Comparado con
watchEffect(),watch()nos permite:- Realizar el efecto secundario de forma perezosa;
- Ser más específico sobre qué estado debe activar la reactivación del watcher;
- Acceder tanto al valor anterior como al actual del estado observado.
Ejemplo
Observando un getter:
jsconst state = reactive({ count: 0 }) watch( () => state.count, (count, prevCount) => { /* ... */ } )Observando un
ref:jsconst count = ref(0) watch(count, (count, prevCount) => { /* ... */ })Cuando se observan múltiples fuentes, la callback recibe arrays que contienen los valores nuevos y antiguos correspondientes al array de fuentes:
jswatch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { /* ... */ })Cuando se usa una fuente getter, el watcher solo se dispara si el valor de retorno del getter ha cambiado. Si deseas que la callback se dispare incluso en mutaciones profundas, debes forzar explícitamente el watcher al modo profundo con
{ deep: true }. Ten en cuenta que en el modo profundo, el valor nuevo y el antiguo serán el mismo objeto si la callback se activó por una mutación profunda:jsconst state = reactive({ count: 0 }) watch( () => state, (newValue, oldValue) => { // newValue === oldValue }, { deep: true } )Cuando se observa directamente un objeto reactivo, el watcher está automáticamente en modo profundo:
jsconst state = reactive({ count: 0 }) watch(state, () => { /* se dispara en mutación profunda a `state` */ })watch()comparte las mismas opciones de momento de ejecución y depuración conwatchEffect():jswatch(source, callback, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })Deteniendo el watcher:
jsconst stop = watch(source, callback) // cuando el watcher ya no sea necesario: stop()Pausando / reanudando el watcher:
jsconst { stop, pause, resume } = watch(() => {}) // pausar temporalmente el watcher pause() // reanudar más tarde resume() // detener stop()Limpieza de efectos secundarios:
jswatch(id, async (newId, oldId, onCleanup) => { const { response, cancel } = doAsyncWork(newId) // `cancel` se llamará si `id` cambia, cancelando // la solicitud anterior si aún no se ha completado onCleanup(cancel) data.value = await response })Limpieza de efectos secundarios en 3.5+:
jsimport { onWatcherCleanup } from 'vue' watch(id, async (newId) => { const { response, cancel } = doAsyncWork(newId) onWatcherCleanup(cancel) data.value = await response })Ver también
onWatcherCleanup()
Registra una función de limpieza para ser ejecutada cuando el watcher actual está a punto de volver a ejecutarse. Solo se puede llamar durante la ejecución síncrona de una función de efecto watchEffect o de una función de callback watch (es decir, no se puede llamar después de una declaración await en una función asíncrona).
Tipo
tsfunction onWatcherCleanup( cleanupFn: () => void, failSilently?: boolean ): voidEjemplo
tsimport { watch, onWatcherCleanup } from 'vue' watch(id, (newId) => { const { response, cancel } = doAsyncWork(newId) // `cancel` se llamará si `id` cambia, cancelando // la solicitud anterior si aún no se ha completado onWatcherCleanup(cancel) })