Lo siento si esto es un duplicado. He buscado esta información, pero no estoy seguro de cuál es la mejor manera de describirla, por lo que encontrarla en las búsquedas de Google ha resultado muy difícil.
Escribo mucho aplicaciones Vue y con frecuencia me encuentro con la siguiente situación en la que tengo un objeto complejo que me gustaría pasar a un componente secundario a través de accesorios para poder encapsular su mutación muy bien y luego tener esos cambios reflejados en el componente principal para que toda esa información esté en un solo lugar.
Considere el siguiente ejemplo sencillo.
// parent.vue // list of complex objects in data export default { data() { return { tickets: [ { name: "ticket 1", price: 20, quantity: 0 }, { name: "ticket 2", price: 20, quantity: 0 }, // etc ] } } } // child.vue // list passed from parent into props export default { props: { tickets: Array } } Para obedecer las mejores prácticas de flujo de datos unidireccional de Vue, debo crear una copia local del accesorio de tickets en niño. Quiero que la copia local se actualice si el padre muta la lista de tickets por cualquier motivo, así que tickets los cambios en la copia local y actualizo la copia local en consecuencia:
// child.vue export default { props: { tickets: Array }, data() { return { _tickets: [] } }, watch: { tickets: { handler: function (value) { // make deep local copy this._tickets = clone(value); }, deep: true, immediate: true } } }Así que ahora tenemos una copia profunda local en la que podemos hacer cambios sin violar el flujo de datos unidireccional de Vue. Quiero que todos mis cambios locales se reflejen en el padre, por lo que observo en profundidad la copia local y emito el valor modificado de nuevo al padre. Apoyos abajo, eventos arriba. Ahora mi componente hijo se ve así:
// child.vue export default { props: { tickets: Array }, data() { return { _tickets: [] } }, watch: { tickets: { handler: function (value) { // make deep local copy this._tickets = clone(value); }, deep: true, immediate: true }, _tickets: { handler: function () { this.$emit('update:tickets', this._tickets); }, deep: true } } } Ahora nos encontramos con un problema. Este es un bucle infinito porque el observador de tickets muta la propiedad _tickets , invocando a su observador y mutando el valor principal, invocando al observador de tickets ... y así sucesivamente. Podría ser posible (no probado) solucionar este problema configurando un indicador en el observador de soporte de ticket para que el bucle quede atrapado antes de volver a emitirlo al padre, pero esto parece una gran cantidad de recursos innecesarios gastados en creando copias solo para cumplir con las mejores prácticas de Vue.
¿Cuál se considera el enfoque correcto para mutar accesorios de objetos complejos?