Propiedades de observación en Vue3

En este capítulo, presentaremos las propiedades de observación de Vue3watch, podemos usarwatchpara responder a los cambios de datos.

watchLa función de watch es monitorear los cambios en las propiedades reactivas y ejecutar operaciones específicas cuando las propiedades cambian. Es un mecanismo reactivo en Vue que te permite responder a los cambios de datos y ejecutar lógica personalizada.

watchEsto proporciona más control y flexibilidad cuando cambian las propiedades reactivas, permitiendo que tus componentes respondan mejor a los cambios de datos y ejecuten la lógica correspondiente.

El siguiente ejemplo implementa un contador usando watch:

Ejemplo

<div id = "app">
    <p style = "font-size:25px;">Contador: {{ counter }}</p>
    <button @click = "counter++" style = "font-size:25px;">Haz clic</button>
</div>
   
<script>
const app = {
  data() {
    return {
      counter: 1
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('counter', function(nval, oval) {
    alert('Cambio del valor del contador :' + oval + ' se convierte en ' + nval + '!');
});
</script>

Pruébalo »

El siguiente ejemplo realizakilómetrosyArrozla conversión entre:

Ejemplo

<div id = "app">
kilómetros: <input type = "text" v-model = "kilometers"  @focus="currentlyActiveField = 'kilometers'">
Arroz: <input type = "text" v-model = "meters" @focus="currentlyActiveField = 'meters'">
</div>
<p id="info"></p>    
<script>
const app = {
  data() {
    return {
      kilometers : 0,
      meters:0
    }
  },
  watch : {
    kilometers:function(newValue, oldValue) {
      // Verifica si es el campo de entrada actual
      if (this.currentlyActiveField === 'kilometers') {
        this.meters = newValue * 1000
      }
    },
    meters : function (newValue, oldValue) {
      // Verifica si es el campo de entrada actual
      if (this.currentlyActiveField === 'meters') {
        this.kilometers = newValue/ 1000;
      }
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('kilometers', function (newValue, oldValue) {
  // Esta devolución de llamada se invocará cuando vm.kilometers cambie
  document.getElementById ("info").innerHTML = "Valor antes de la modificación: " + oldValue + ", el valor después de la modificación es: " + newValue;
})
</script>

Pruébalo »

Haz clic en el botón "Pruébalo" para ver el ejemplo en línea

En el código anterior, creamos dos campos de entrada. En la propiedad data, los valores iniciales de kilometers y meters son ambos 0. El objeto watch crea dos métodos de supervisión para el objeto data: kilometers y meters.

Cuando ingresamos datos en el campo de entrada, watch monitorea los cambios de datos en tiempo real y actualiza su propio valor. Puedes ver la siguiente demostración en video:

Usar watch en la carga asíncrona

Para la carga de datos asíncronos, Vue proporciona un método más general a través de la opción watch para responder a los cambios de datos.

En el siguiente ejemplo usamos la librería axios, que se presentará en detalle más adelante.

Ejemplo

<!--Debido a que el ecosistema de librerías AJAX y herramientas generales ya es bastante rico, el código central de Vue no vuelve a proporcionar-->
<!--estas funciones para mantenerse simple. Esto también te permite elegir libremente las herramientas con las que estás más familiarizado.-->
<script src="https://cdn.staticfile.org/axios/0.27.2/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue/3.2.37/vue.global.min.js"></script>
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        question: '',
        answer: 'Cada pregunta debe terminar con un signo ?.'
      }
    },
    watch: {
      // Cada vez que la pregunta cambie, esta función se ejecutará, terminando con el signo ?, compatible con el ? en chino e inglés.
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = 'Cargando...'
        axios
          .get('/try/ajax/json_vuetest.php')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = '¡Error! No se puede acceder a la API. ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>

Pruébalo »

Resumen de uso

watch es un mecanismo de observación de datos reactivos proporcionado por Vue 3, que puede observar una o múltiples propiedades.

Puedes manejar los cambios de datos pasando una función de devolución de llamada, y admite opciones como observación profunda y ejecución inmediata.

1. Uso básico

En Vue 3, la función watch se usa para observar propiedades reactivas.

Cuando el valor de la propiedad observada cambia, Vue activa la ejecución de la función de devolución de llamada.

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // Propiedad observada
      (newVal, oldVal) => { // Función de devolución de llamada al cambiar
        console.log(`count changed from ${oldVal} to ${newVal}`);
      }
    );

    return {
      state
    };
  }
};

2. Observar múltiples propiedades reactivas

Si deseas observar varias propiedades reactivas a la vez, puedes pasar un array con las propiedades a observar:

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    watch(
      [() => state.count, () => state.name], // Observar múltiples propiedades
      ([newCount, newName], [oldCount, oldName]) => {
        console.log(`count changed from ${oldCount} to ${newCount}`);
        console.log(`name changed from ${oldName} to ${newName}`);
      }
    );

    return {
      state
    };
  }
};

3. Observación profunda

Si lo que quieres observar es un objeto o un array, y deseas observar sus propiedades anidadas, puedes usardeep: truela opción. Esto observará todos los cambios de propiedades del objeto.

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      user: {
        name: 'Alice',
        age: 25
      }
    });

    watch(
      () => state.user, // Observar el objeto completo
      (newVal, oldVal) => {
        console.log('User object changed:', newVal, oldVal);
      },
      { deep: true } // Habilitar la observación profunda
    );

    return {
      state
    };
  }
};

4. Ejecución inmediata

De forma predeterminada, watch solo activa la devolución de llamada cuando el valor observado cambia. Si deseas que la devolución de llamada se ejecute inmediatamente al cargar el componente, puedes configurarimmediate: true。

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // Propiedad observada
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { immediate: true } // Ejecución inmediata
    );

    return {
      state
    };
  }
};

5. Operaciones asíncronas

Si necesitas realizar operaciones asíncronas en watch, puedes usar async y await directamente en la función de devolución de llamada, lo que te permite manejar operaciones como solicitudes a API, almacenamiento de datos, etc.

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      async (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
        // Supongamos que se realiza una solicitud asíncrona
        await fetch(`https://api.example.com/count/${newVal}`);
      }
    );

    return {
      state
    };
  }
};

6. Observar múltiples propiedades y usar la función handler

También puedes usar watch como un controlador para observar múltiples propiedades, así:

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    const handler = ([newCount, newName], [oldCount, oldName]) => {
      console.log(`count changed: ${oldCount} → ${newCount}`);
      console.log(`name changed: ${oldName} → ${newName}`);
    };

    watch([() => state.count, () => state.name], handler);

    return {
      state
    };
  }
};

7. watchEffect: una versión simplificada de observación

Vue 3 también proporciona la API watchEffect, que es más concisa que watch, ya que puede rastrear automáticamente los cambios en los datos reactivos sin necesidad de especificar una fuente de datos concreta.

Ejemplo

import { reactive, watchEffect } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watchEffect(() => {
      console.log(`count is: ${state.count}`);
    });

    return {
      state
    };
  }
};

watchEffect detectará automáticamentestate.countlos cambios y activará la devolución de llamada cuando estos ocurran.

8. Opción flush

La opción flush se usa para controlar el momento en que se ejecuta la devolución de llamada de watch.

De forma predeterminada, la devolución de llamada de watch se ejecuta después de la actualización del DOM. Si necesitas ejecutar la devolución de llamada antes de la actualización, puedes usarflush: 'pre'。

Ejemplo

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { flush: 'pre' } // Ejecutar la devolución de llamada antes de la actualización
    );

    return {
      state
    };
  }
};
Otras extensiones