Índice
La reactividad es la capacidad de una variable (matriz, cadena, número, objeto, etc.) de actualizarse cuando su valor o cualquier otra variable a la que hace referencia cambia después de la declaración.
En este artículo, veremos la reactividad en Vue, cómo funciona y cómo podemos crear variables reactivas utilizando métodos y funciones recién creados. Este artículo está dirigido a desarrolladores que comprenden bien cómo funciona Vue 2.x y desean familiarizarse con el nuevo Vue 3 .
Vamos a crear una aplicación sencilla para comprender mejor este tema. El código de esta aplicación se puede encontrar en GitHub .
De forma predeterminada, JavaScript no es reactivo . Esto significa que si creamos la variable boy
y hacemos referencia a ella en la parte A de nuestra aplicación, luego procedemos a modificarla boy
en la parte B, la parte A no se actualizará con el nuevo valor de boy
.
let framework = 'Vue';let sentence = `${framework} is awesome`;console.log(sentence) // logs "Vue is awesome"framework = 'React';console.log(sentence)//should log "React is awesome" if 'sentence' is reactive.
El fragmento anterior es un ejemplo perfecto de la naturaleza no reactiva de JavaScript; de ahí que el cambio no se refleje en la sentence
variable.
En Vue 2.x, props
, computed
y data()
eran todos reactivos de forma predeterminada, con la excepción de las propiedades que no están presentes data
cuando se crean dichos componentes. Esto significa que cuando un componente se inyecta en el DOM , solo las propiedades existentes en el objeto del componente data
harían que el componente se actualice si dichas propiedades cambian.
Internamente, Vue 3 usa el Proxy
objeto (una característica de ECMAScript 6) para garantizar que estas propiedades sean reactivas, pero aún brinda la opción de usarlo Object.defineProperty
desde Vue 2 para compatibilidad con Internet Explorer (ECMAScript 5). Este método define una nueva propiedad directamente en un objeto, o modifica una propiedad existente en un objeto y devuelve el objeto.
A primera vista y como la mayoría de nosotros ya sabemos que la reactividad no es nueva en Vue, puede parecer innecesario hacer uso de estas propiedades, pero la API de Opciones tiene sus limitaciones cuando se trata de una aplicación grande con funciones reutilizables en varios partes de la aplicación. Con este fin, se introdujo la nueva API de composición para ayudar a abstraer la lógica y hacer que el código base sea más fácil de leer y mantener. Además, ahora podemos hacer que cualquier variable sea reactiva independientemente de su tipo de datos utilizando cualquiera de las nuevas propiedades y métodos.
Cuando usamos la setup
opción, que sirve como punto de entrada para la API de composición, el data
objeto, computed
las propiedades y methods
son inaccesibles porque la instancia del componente aún no se ha creado cuando setup
se ejecuta. Esto hace que sea imposible aprovechar la reactividad incorporada en cualquiera de estas características en setup
. En este tutorial, aprenderemos todas las formas en que podemos hacer esto.
El método reactivo
Según la documentación, el reactive
método, que es equivalente a Vue.observable()
Vue 2.6, puede ser útil cuando intentamos crear un objeto cuyas propiedades sean reactivas (como el data
objeto en la API de opciones). Debajo del capó, el data
objeto en la API de opciones usa este método para hacer que todas las propiedades que contiene sean reactivas.
Pero podemos crear nuestro propio objeto reactivo así:
import { reactive } from 'vue'// reactive statelet user = reactive({ "id": 1, "name": "Leanne Graham", "username": "Bret", "email": "[email protected]", "address": { "street": "Kulas Light", "suite": "Apt. 556", "city": "Gwenborough", "zipcode": "92998-3874", "geo": { "lat": "-37.3159", "lng": "81.1496" } }, "phone": "1-770-736-8031 x56442", "website": "hildegard.org", "company": { "name": "Romaguera-Crona", "catchPhrase": "Multi-layered client-server neural-net", "bs": "harness real-time e-markets" }, "cars": { "number": 0 } })
Aquí, importamos el reactive
método de Vue y luego declaramos nuestra user
variable pasando su valor a esta función como argumento. Al hacerlo, lo hemos hecho user
reactivo y, por lo tanto, si lo usamos user
en nuestra plantilla y si el objeto o una propiedad de este objeto debe cambiar, entonces este valor se actualizará automáticamente en esta plantilla.
ref
Así como tenemos un método para hacer que los objetos sean reactivos, también necesitamos uno para hacer que otros valores primitivos independientes (cadenas, valores booleanos, valores indefinidos, números, etc.) y matrices sean reactivos. Durante el desarrollo, trabajaríamos con estos otros tipos de datos y al mismo tiempo necesitaríamos que fueran reactivos. El primer enfoque que podríamos pensar sería usar reactive
y pasar el valor de la variable que queremos hacer reactiva.
import { reactive } from 'vue'const state = reactive({ users: [],});
Porque reactive
tiene una conversión reactiva profunda, user
ya que una propiedad también sería reactiva, logrando así nuestro objetivo; por lo tanto, user
siempre se actualizará en cualquier lugar donde se use en la plantilla de dicha aplicación. Pero con la ref
propiedad, podemos hacer que cualquier variable con cualquier tipo de datos sea reactiva pasando el valor de esa variable a ref
. Este método también funciona para objetos, pero anida el objeto un nivel más profundo que cuando reactive
se utiliza el método.
let property = { rooms: '4 rooms', garage: true, swimmingPool: false}let reactiveProperty = ref(property)console.log(reactiveProperty)// prints {// value: {rooms: "4 rooms", garage: true, swimmingPool: false}// }
Debajo del capó, ref
toma este argumento que se le pasa y lo convierte en un objeto con una clave de value
. Esto significa que podemos acceder a nuestra variable llamando variable.value
y también podemos modificar su valor llamándola de la misma manera.
import {ref} from 'vue'let age = ref(1)console.log(age.value)//prints 1age.value++console.log(age.value)//prints 2
Con esto, podemos importar ref
a nuestro componente y crear una variable reactiva:
template div form @click.prevent="" table tr thName/th thUsername/th themail/th thEdit Cars/th thCars/th /tr tr v-for="user in users" :key="user.id" td{{ user.name }}/td td{{ user.username }}/td td{{ user.email }}/td td input type="number" name="cars" v-model.number="user.cars.number" / /td td cars-number :cars="user.cars" / /td /tr /table pTotal number of cars: {{ getTotalCars }}/p /form /div/templatescript // @ is an alias to /src import carsNumber from "@/components/cars-number.vue"; import axios from "axios"; import { ref } from "vue"; export default { name: "Home", data() { return {}; }, setup() { let users = ref([]); const getUsers = async () = { let { data } = await axios({ url: "data.json", }); users.value = data; }; return { users, getUsers, }; }, components: { carsNumber, }, created() { this.getUsers(); }, computed: { getTotalCars() { let users = this.users; let totalCars = users.reduce(function(sum, elem) { return sum + elem.cars.number; }, 0); return totalCars; }, };/script
Aquí, importamos ref
para crear una users
variable reactiva en nuestro componente. Luego importamos axios
para recuperar datos de un archivo JSON en la public
carpeta e importamos nuestro carsNumber
componente, que crearemos más adelante. Lo siguiente que hicimos fue crear una users
variable reactiva usando el ref
método, para que users
pueda actualizarse cada vez que cambie la respuesta de nuestro archivo JSON.
También creamos una getUser
función que recupera la users
matriz de nuestro archivo JSON usando axios y asignamos el valor de esta solicitud a la users
variable. Finalmente, creamos una propiedad calculada que calcula la cantidad total de automóviles que tienen nuestros usuarios tal como la modificamos en la sección de plantilla.
Es importante tener en cuenta que al acceder a ref
las propiedades que se devuelven en la sección de plantilla o fuera de ella setup()
, se desenvuelven automáticamente de forma superficial . Esto significa que refs
ese es un objeto aún requeriría un .value
para poder acceder. Como users
es una matriz, simplemente podríamos usarla users
y no users.value
en getTotalCars
.
En la sección de plantilla, mostramos una tabla que muestra la información de cada usuario, junto con un cars-number /
componente. Este componente acepta un cars
accesorio que se muestra en la fila de cada usuario como la cantidad de autos que tiene. Este valor se actualiza cada vez que cambia el valor cars
del objeto de usuario , que es exactamente cómo funcionaría el data
objeto o propiedad si estuviéramos trabajando con la API de opciones.computed
toRefs
Cuando usamos la API de composición, la setup
función acepta dos argumentos: props
y context
. Esto props
se pasa del componente a setup()
y permite acceder a los accesorios que tiene el componente desde dentro de esta nueva API. Este método es particularmente útil porque permite desestructurar objetos sin perder su reactividad.
template p{{ cars.number }}/p/templatescript export default { props: { cars: { type: Object, required: true, }, gender: { type: String, required: true, }, }, setup(props) { console.log(props); // prints {gender: "female", cars: Proxy} }, };/scriptstyle/style
Para utilizar un valor que es un objeto props
en la API de composición y al mismo tiempo garantizar que mantenga su reactividad, utilizamos toRefs
. Este método toma un objeto reactivo y lo convierte en un objeto simple en el que cada propiedad del objeto reactivo original se convierte en un archivo ref
. Lo que esto significa es que la cars
propiedad...
cars: { number: 0}
… ahora se convertiría en esto:
{ value: cars: { number: 0 }
Con esto, podemos hacer uso de cars
cualquier parte de la API de configuración manteniendo su reactividad.
setup(props) { let { cars } = toRefs(props); console.log(cars.value); // prints {number: 0} },
Podemos observar esta nueva variable utilizando las API de composición watch
y reaccionar a este cambio como queramos.
setup(props) { let { cars } = toRefs(props); watch( () = cars, (cars, prevCars) = { console.log("deep ", cars.value, prevCars.value); }, { deep: true } ); }
toRef
Otro caso de uso común al que nos podríamos enfrentar es pasar un valor que no es necesariamente un objeto sino uno de los tipos de datos con los que funciona ref
(matriz, número, cadena, booleano, etc.). Con toRef
, podemos crear una propiedad reactiva (es decir, ref
) a partir de un objeto reactivo de origen. Hacer esto garantizaría que la propiedad permanezca reactiva y se actualizaría cada vez que cambie la fuente principal.
const cars = reactive({ Toyota: 1, Honda: 0})const NumberOfHondas = toRef(state, 'Honda')NumberOfHondas.value++console.log(state.Honda) // 1state.Honda++console.log(NumberOfHondas.value) // 2
Aquí, creamos un objeto reactivo usando el reactive
método, con las propiedades Toyota
y Honda
. También utilizamos toRef
para crear una variable reactiva a partir de Honda
. En el ejemplo anterior, podemos ver que cuando actualizamos Honda
usando el objeto reactivo cars
o NumberOfHondas
, el valor se actualiza en ambos casos.
Este método es similar y, sin embargo, muy diferente del toRefs
método que cubrimos anteriormente en el sentido de que mantiene su conexión con su fuente y puede usarse para cadenas, matrices y números. A diferencia de con toRefs
, no necesitamos preocuparnos por la existencia de la propiedad en su fuente en el momento de la creación, porque si esta propiedad no existe en el momento en que se ref
crea y en su lugar regresa null
, aún se almacenará como un archivo válido. propiedad, con una forma de watcher
poner en marcha, de modo que cuando este valor cambie, este ref
uso creado toRef
también se actualizará.
También podemos usar este método para crear una propiedad reactiva a partir de props
. Se vería así:
template p{{ cars.number }}/p/templatescript import { watch, toRefs, toRef } from "vue"; export default { props: { cars: { type: Object, required: true, }, gender: { type: String, required: true, }, }, setup(props) { let { cars } = toRefs(props); let gender = toRef(props, "gender"); console.log(gender.value); watch( () = cars, (cars, prevCars) = { console.log("deep ", cars.value, prevCars.value); }, { deep: true } ); }, };/script
Aquí, creamos un ref
que se basaría en la gender
propiedad obtenida de props
. Esto resulta útil cuando queremos realizar operaciones adicionales en el accesorio de un componente en particular.
Conclusión
En este artículo, analizamos cómo funciona la reactividad en Vue utilizando algunos de los métodos y funciones recientemente introducidos en Vue 3. Comenzamos analizando qué es la reactividad y cómo Vue utiliza el Proxy
objeto detrás de escena para lograrlo. También vimos cómo podemos crear objetos reactivos usando reactive
y cómo crear propiedades reactivas usando ref
.
Finalmente, vimos cómo convertir objetos reactivos en objetos simples, cada una de cuyas propiedades apunta ref
a la propiedad correspondiente del objeto original, y vimos cómo crear una ref
propiedad en un objeto fuente reactivo.
Recursos adicionales
- “ Proxy ” (objeto), MDN Web Docs
- “ Fundamentos de reactividad ”, Vue.js
- “ Referencias ”, Vue.js
- “ Registro del gancho del ciclo de vida interno
setup
”, Vue.js
(ks, vf, yk, il, al)Explora más en
- vista
- javascript
- Marcos
Tal vez te puede interesar:
- ¿Deberían abrirse los enlaces en ventanas nuevas?
- 24 excelentes tutoriales de AJAX
- 70 técnicas nuevas y útiles de AJAX y JavaScript
- Más de 45 excelentes recursos y repositorios de fragmentos de código
Reactividad en Vue
El método reactivoreftoRefstoRefConclusiónAccesibilidad para diseñadores, con Stéphanie Walter Creación y mantenimiento de sistemas de diseño exitosos,
programar
es
2025-01-15
Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente