Tengo un componente personalizado que toma la propiedad modelValue y emite el evento update:modelValue . En el componente principal, paso una matriz:
TestComponent.vue
<template> <div> <button @click="updateIt">Test</button> </div> </template> <script> export default { props: { modelValue: Array }, emits: ["update:modelValue"], setup(props, {emit}){ return { updateIt(){ emit("update:modelValue", [4,5,6]) } } } } </script>aplicación.vue
<template> <div> <test-component v-model="myArr"/> <ul> <li v-for="i in myArr" v-text="i"></li> </ul> </div> </template> <script> import TestComponent from "./TestComponent.vue"; export default { components: { TestComponent }, setup(props, {emit}){ const myArr = reactive([1,2,3]); return { myArr } } } </script>La lista no se actualiza cuando presiono el botón, ¿por qué?
Internamente, la directiva v-model se cambia a una función de controlador para el evento update:modelValue que se parece a esto:
$event => ((exp => $event) donde exp es la expresión en la directiva
lo que básicamente significa que, cuando se emite el evento update:modelValue , el valor que emite se asigna directamente a la variable myArr , reemplazando efectivamente toda la variable reactive sin desencadenar la cadena de reactividad, porque no ocurre a través del proxy.
Si myArr fuera una ref([]) vue lo detecta y la función del controlador se parece a esto:
$event => (exp ? (exp).value = $event : null) donde exp es la expresión en la directiva
lo que significa que el valor se asigna a través del proxy ref, lo que desencadena la cadena de reactividad.
Pero no hay una lógica interna que verifique si la expresión pasada es una matriz y, de ser así, hace algo de magia de empalme para mantener la variable original, tiene que hacerlo usted mismo.
<test-component v-model="myArr.data"/> ... const myArr = reactive({ data: [1,2,3] }); <test-component v-model="myArr"/> ... const myArr = ref([1,2,3]); <test-component :modelValue="myArr" @update:modelValue="onChange"/> ... const myArr = reactive([1,2,3]); function onChange(newval){ myArr.splice(0, myArr.length, ...newval); }