Estoy tratando de lograr algo bastante complicado con respecto al uso de múltiples propiedades computadas interdependientes.
Mi pregunta inicial es la siguiente: tenemos un valor calculado A y un valor calculado B. B tiene A como dependencia. Ahora, las dependencias de A cambian, pero el valor de salida sigue siendo el mismo, por lo que se vuelve a calcular pero devuelve el mismo valor.
Por lo que descubrí en mi investigación, incluso si el valor de salida de A no cambia, si A se vuelve a calcular, entonces B se volverá a calcular. Quiero saber si hay una manera de lograr este comportamiento
Para brindarle contexto, primero permítame darle un ejemplo concreto que se acerque lo suficiente a mi caso de uso real:
<script setup> import { ref, reactive, computed } from 'vue'; const formState = reactive({ field1: '', field2: { field2Child: 'MyChildVal', }, }); const mapDependencies = (arrayDependencies) => { let dependencies = {}; for (const { key, value } of arrayDependencies) dependencies[key] = value; return dependencies; }; const resolveFromString = (path, obj, separator = '.') => { var properties = Array.isArray(path) ? path : path.split(separator); return properties.reduce((prev, curr) => prev && prev[curr], obj); }; const listDependencies = ['field2.field2Child']; // Will re-render every time formState changes const dependencies = computed(() => mapDependencies( listDependencies.map((key) => ({ key, value: resolveFromString(key, Object.assign({}, formState)), })) ) ); const dependenciesAsString = (dependencies) => { return 'The dependencies are' + Object.entries(dependencies).map(([key, value]) => `${key} : ${value}`); } // Expected to re-render only when the output of "dependencies" changes. But on real usage const computedBasedOnDependencies = computed(() => dependenciesAsString(Object.assign({}, dependencies.value))); const ChangeState = () => formState.field1 = new Date().toString(); </script>Creé una reproducción en vivo de esto de stackblitz: https://stackblitz.com/edit/vue-svtsu2?file=src/App.vue
El comportamiento que esperaba de esto: si la salida de "dependencias" no cambia, entonces la marca de tiempo al comienzo de "computedBasedOnDependencies" no debería cambiar
El comportamiento que obtengo: incluso cuando la salida de "dependencias" no cambia, cuando se vuelve a calcular "computedBasedOnDependencies" también se vuelve a calcular
Si tiene alguna idea sobre algo que no entiendo correctamente de la reactividad de Vue, o cualquier otra forma de lograr este comportamiento, agradezco cualquier ayuda.
¡Gracias por adelantado!
Se supone que las funciones de propiedad calculadas son funciones puras, es decir, no tienen efectos secundarios y la salida de la función depende solo de la entrada.
Para cualquier otra lógica, se debe usar un observador. Este es el caso de un observador, donde se puede limitar con la función de fuente y/o una comparación de valor antiguo y nuevo:
const computedBasedOnDependencies = ref(null); watch( () => stringifyWithoutTimestamp(dependencies.value)), (val, oldVal) => { if (val !== oldVal) computedBasedOnDependencies.value = stringifyWithTimestamp(dependencies.value); }, { immediate: true } );Incluso cuando la salida de "dependencias" no cambia ...
Bueno, el problema es que está cambiando , incluso si devuelve el objeto con el mismo contenido que antes, sigue siendo un objeto nuevo.
function getObject() { return { value: "A" } } const a = getObject() const b = getObject() console.log(a === b) Vue no realiza una comparación "profunda", ya que sería un gran impacto en el rendimiento (el valor devuelto por el computed puede ser cualquier cosa, por ejemplo, un objeto profundamente anidado). Entonces, si necesita esto, debe implementarlo usted mismo, presumiblemente usando watch en lugar de computed
Pero antes de tomar esa ruta, debe asegurarse de que lo que está haciendo no es solo una optimización prematura.