Свойства Watch в Vue3

В этой главе мы представим свойства watch в Vue3watch, мы можем использоватьwatchдля реагирования на изменения данных.

watchОн используется для отслеживания изменений реактивных свойств и выполнения определённых операций при изменении свойств. Это реактивный механизм в Vue, который позволяет соответствующим образом реагировать на изменения данных и выполнять пользовательскую логику.

watchОн обеспечивает больший контроль и гибкость при изменении реактивных свойств, позволяя вашим компонентам лучше реагировать на изменения данных и выполнять соответствующую логику.

Следующий пример реализует счётчик с помощью watch:

Пример

<div id = "app">
    <p style = "font-size:25px;">Счётчик: {{ counter }}</p>
    <button @click = "counter++" style = "font-size:25px;">Нажми меня</button>
</div>
   
<script>
const app = {
  data() {
    return {
      counter: 1
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('counter', function(nval, oval) {
    alert('Значение счётчика изменилось:' + oval + ' изменено на ' + nval + '!');
});
</script>

Попробуйте сами »

В следующем примере выполняетсяkilometersиRiceпреобразование между:

Пример

<div id = "app">
Километры: <input type = "text" v-model = "kilometers"  @focus="currentlyActiveField = 'kilometers'">
Рис: <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) {
      // Проверяем, является ли это текущим полем ввода
      if (this.currentlyActiveField === 'kilometers') {
        this.meters = newValue * 1000
      }
    },
    meters : function (newValue, oldValue) {
      // Проверяем, является ли это текущим полем ввода
      if (this.currentlyActiveField === 'meters') {
        this.kilometers = newValue/ 1000;
      }
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('kilometers', function (newValue, oldValue) {
  // Этот обратный вызов будет вызван после изменения vm.kilometers
  document.getElementById ("info").innerHTML = "Значение до изменения: " + oldValue + ", значение после изменения: " + newValue;
})
</script>

Попробуйте сами »

Нажмите кнопку "Попробуйте сами", чтобы просмотреть онлайн-пример.

В приведённом выше коде мы создали два поля ввода. В свойстве data начальные значения kilometers и meters равны 0. Объект watch создаёт два метода наблюдения для объекта data: kilometers и meters.

Когда мы вводим данные в поле ввода, watch будет отслеживать изменения данных в реальном времени и изменять своё собственное значение. Вы можете посмотреть видео-демонстрацию ниже:

Использование watch при асинхронной загрузке

Для загрузки асинхронных данных Vue предоставляет более общий метод через опцию watch, чтобы реагировать на изменения данных.

В следующем примере используется библиотека axios, которая будет подробно представлена позже.

Пример

<!--Поскольку экосистема библиотек AJAX и инструментов общего назначения уже довольно богата, основной код Vue не дублирует-->
<!--эти возможности, чтобы оставаться лёгким. Это также позволяет вам свободно выбирать инструменты, с которыми вы более знакомы.-->
<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: 'Каждый вопрос должен заканчиваться знаком ?.'
      }
    },
    watch: {
      // Всякий раз, когда вопрос изменяется, эта функция будет выполняться, требуя, чтобы вопрос заканчивался знаком ?; совместимо с китайским и английским ?
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = 'Загрузка...'
        axios
          .get('/try/ajax/json_vuetest.php')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = 'Ошибка! Не удалось получить доступ к API. ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>

Попробуйте сами »

Сводка использования

watch — это механизм реактивного отслеживания данных, предоставляемый Vue 3, который может отслеживать одно или несколько свойств.

Вы можете обрабатывать изменения данных, передавая функцию обратного вызова, с поддержкой таких опций, как глубокое отслеживание и немедленное выполнение.

1. Базовое использование

В Vue 3 функция watch используется для отслеживания реактивных свойств.

Когда значение отслеживаемого свойства изменяется, Vue вызывает функцию обратного вызова для выполнения.

Пример

import { reactive, watch } from 'vue';

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

    watch(
      () => state.count, // Отслеживаемое свойство
      (newVal, oldVal) => { // Функция обратного вызова при изменении
        console.log(`count изменился с ${oldVal} на ${newVal}`);
      }
    );

    return {
      state
    };
  }
};

2. Отслеживание нескольких реактивных свойств

Если вы хотите отслеживать несколько реактивных свойств одновременно, вы можете передать массив, содержащий свойства для отслеживания:

Пример

import { reactive, watch } from 'vue';

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

    watch(
      [() => state.count, () => state.name], // Отслеживание нескольких свойств
      ([newCount, newName], [oldCount, oldName]) => {
        console.log(`count изменился с ${oldCount} на ${newCount}`);
        console.log(`name изменилось с ${oldName} на ${newName}`);
      }
    );

    return {
      state
    };
  }
};

3. Глубокое отслеживание

Если вы хотите отслеживать объект или массив и хотите отслеживать его вложенные свойства, вы можете использовать опциюdeep: true. Это позволит отслеживать все изменения свойств объекта.

Пример

import { reactive, watch } from 'vue';

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

    watch(
      () => state.user, // Отслеживать весь объект
      (newVal, oldVal) => {
        console.log('Объект пользователя изменён:', newVal, oldVal);
      },
      { deep: true } // Включить глубокое отслеживание
    );

    return {
      state
    };
  }
};

4. Немедленное выполнение

По умолчанию watch вызывает колбэк только при изменении отслеживаемого значения. Если вы хотите, чтобы колбэк выполнялся сразу при загрузке компонента, можно установитьimmediate: true。

Пример

import { reactive, watch } from 'vue';

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

    watch(
      () => state.count, // Отслеживать свойство
      (newVal, oldVal) => {
        console.log(`count изменился с ${oldVal} на ${newVal}`);
      },
      { immediate: true } // Немедленное выполнение
    );

    return {
      state
    };
  }
};

5. Асинхронные операции

Если вам нужно выполнять асинхронные операции в watch, вы можете напрямую использовать async и await в функции обратного вызова, что позволяет обрабатывать такие операции, как API-запросы, сохранение данных и т. д.

Пример

import { reactive, watch } from 'vue';

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

    watch(
      () => state.count,
      async (newVal, oldVal) => {
        console.log(`count изменился с ${oldVal} на ${newVal}`);
        // Предположим, что выполняется асинхронный запрос
        await fetch(`https://api.example.com/count/${newVal}`);
      }
    );

    return {
      state
    };
  }
};

6. Отслеживание нескольких свойств и использование функции handler

Вы также можете использовать watch в качестве обработчика для наблюдения за несколькими свойствами, вот так:

Пример

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 — упрощённое отслеживание

Vue 3 также предоставляет API watchEffect, который более краток, чем watch. Он может автоматически отслеживать изменения в реактивных данных без необходимости указывать конкретный источник данных.

Пример

import { reactive, watchEffect } from 'vue';

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

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

    return {
      state
    };
  }
};

watchEffect будет автоматически обнаруживатьstate.countизменения и запускать callback при возникновении изменений.

8. Опция flush

Опция flush используется для управления моментом выполнения колбэков watch.

По умолчанию колбэки watch выполняются после обновления DOM. Если нужно выполнить колбэк до обновления, можно использоватьflush: 'pre'。

Пример

import { reactive, watch } from 'vue';

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

    watch(
      () => state.count,
      (newVal, oldVal) => {
        console.log(`count изменился с ${oldVal} на ${newVal}`);
      },
      { flush: 'pre' } // Выполнить колбэк до обновления
    );

    return {
      state
    };
  }
};
Другие расширения