# Методы экземпляра

# $watch

  • Аргументы:

    • {string | Function} source
    • {Function | Object} callback
    • {Object} options (опционально)
      • {boolean} deep
      • {boolean} immediate
      • {string} flush
  • Возвращает: {Function} unwatch

  • Использование:

    Отслеживание изменений реактивного свойства или функции вычисляемого свойства на экземпляре компонента. Коллбэк будет вызываться с новым и старым значениями. В виде строки можно указывать только имена свойств корневого уровня для data, props или computed. Для сложных выражений или вложенных свойств стоит определять функцию.

  • Пример:

    const app = createApp({
      data() {
        return {
          a: 1,
          b: 2,
          c: {
            d: 3,
            e: 4
          }
        }
      },
      created() {
        // имя свойства корневого уровня
        this.$watch('a', (newVal, oldVal) => {
          // сделать что-нибудь
        })
    
        // функция для отслеживания одного вложенного свойства
        this.$watch(
          () => this.c.d,
          (newVal, oldVal) => {
            // сделать что-нибудь
          }
        )
    
        // функция для отслеживания сложного выражения
        this.$watch(
          // каждый раз, когда выражение `this.a + this.b` получит другой
          // результат — будет вызываться коллбэк. Это похоже на отслеживание
          // вычисляемого свойства, но без необходимости его объявлять
          () => this.a + this.b,
          (newVal, oldVal) => {
            // сделать что-нибудь
          }
        )
      }
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37

    При отслеживании объекта или массива, любые изменения свойств или элементов в них не будут вызывать коллбэк, потому что они ссылаются на один и тот же объект/массив:

    const app = createApp({
      data() {
        return {
          article: {
            text: 'Vue крутой!'
          },
          comments: ['Да!', 'Согласен']
        }
      },
      created() {
        this.$watch('article', () => {
          console.log('Заметка обновилась!')
        })
    
        this.$watch('comments', () => {
          console.log('Комментарии обновились!')
        })
      },
      methods: {
        // Такие методы НЕ ВЫЗОВУТ коллбэк метода-наблюдателя, потому что
        // изменится только свойство объекта/массива, но не объект/массив целиком
        changeArticleText() {
          this.article.text = 'Vue 3 крутой'
        },
        addComment() {
          this.comments.push('Новый комментарий')
        },
    
        // Такие методы ВЫЗОВУТ коллбэк метода-наблюдателя, потому что
        // заменяется объект/массив целиком
        changeWholeArticle() {
          this.article = { text: 'Vue 3 крутой' }
        },
        clearComments() {
          this.comments = []
        }
      }
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    Метод $watch также возвращает функцию для возможности остановить отслеживание:

    const app = createApp({
      data() {
        return {
          a: 1
        }
      }
    })
    
    const vm = app.mount('#app')
    
    const unwatch = vm.$watch('a', cb)
    
    // ... когда-то позднее, останавливаем дальнейшее отслеживание
    unwatch()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  • Опция: deep

    Для отслеживания изменений вложенных значений внутри объектов нужно передавать в опциях deep: true. Её можно также использовать и для отслеживания мутаций массива.

    Обратите внимание: при мутации (а не замене) объекта/массива и их отслеживании с помощью опции deep, старое значение будет таким же, как и новое, потому что они ссылаются на один и тот же объект/массив. Vue не хранит копию значения до мутации.

    vm.$watch('someObject', callback, {
      deep: true
    })
    
    vm.someObject.nestedValue = 123
    // коллбэк будет вызван
    
    1
    2
    3
    4
    5
    6
  • Опция: immediate

    При передаче в опциях immediate: true, коллбэк будет вызываться сразу же, с текущим значением отслеживаемого выражения:

    vm.$watch('a', callback, {
      immediate: true
    })
    
    // `callback` будет вызван сразу же, с текущим значением `a`
    
    1
    2
    3
    4
    5

    Обратите внимание, при использовании опции immediate нет возможности остановить отслеживание при первом вызове коллбэка.






     

     


    // подобное выбросит ОШИБКУ
    const unwatch = vm.$watch(
      'value',
      function() {
        doSomething()
        unwatch()
      },
      { immediate: true }
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    При необходимости останавливать отслеживание в коллбэке следует сначала проверять его доступность:

     





     
     
     




    let unwatch = null
    
    unwatch = vm.$watch(
      'value',
      function() {
        doSomething()
        if (unwatch) {
          unwatch()
        }
      },
      { immediate: true }
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • Опция: flush

    Опция flush позволяет точнее контролировать время вызова коллбэка. Значением может быть 'pre', 'post' или 'sync'.

    По умолчанию значение 'pre'. Это значит, что коллбэк должен быть вызван перед отрисовкой. Это позволяет в коллбэке обновить другие значения перед обновлением шаблона.

    Значение 'post' можно использовать для отложенного вызова коллбэка по окончанию отрисовки. Его следует использовать, если в коллбэке требуется доступ к обновлённому DOM или дочерним компонентам через $refs.

    При установке опции flush в значение 'sync', коллбэк будет вызываться синхронно, как только значение изменится.

    Для значений 'pre' и 'post' коллбэк будет буферизироваться с использованием очереди. Он будет добавляться в очередь только один раз, даже если отслеживаемое значение изменилось несколько раз. Промежуточные значения будут пропущены и не будут переданы в коллбэк.

    Буферизация коллбэка позволяет не только улучшить производительность, но и помогает обеспечить консистентность данных. Методы-наблюдатели не будут вызываться до тех пор, пока не завершится код, занимающийся обновлением данных.

    Значение 'sync' следует применять редко и очень аккуратно, потому что у него нет этих преимуществ.

    Дополнительную информацию об опции flush можно прочитать в разделе синхронизации времени очистки эффектов.

  • См. также: Методы-наблюдатели

# $emit

  • Аргументы:

    • {string} eventName
    • ...args (опционально)

    Генерирует событие на текущем экземпляре. Любые дополнительные аргументы будут переданы в коллбэк функции прослушивания события.

  • Примеры:

    Использование $emit только определяя имя события:

    <div id="emit-example-simple">
      <welcome-button v-on:welcome="sayHi"></welcome-button>
    </div>
    
    1
    2
    3
    const app = createApp({
      methods: {
        sayHi() {
          console.log('Привет!')
        }
      }
    })
    
    app.component('welcome-button', {
      emits: ['welcome'],
      template: `
        <button v-on:click="$emit('welcome')">
          Кликни для приветствия
        </button>
      `
    })
    
    app.mount('#emit-example-simple')
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    Использование $emit с передачей дополнительных аргументов:

    <div id="emit-example-argument">
      <advice-component v-on:advice="showAdvice"></advice-component>
    </div>
    
    1
    2
    3
    const app = createApp({
      methods: {
        showAdvice(advice) {
          alert(advice)
        }
      }
    })
    
    app.component('advice-component', {
      emits: ['advise'],
      data() {
        return {
          adviceText: 'Какой-то совет'
        }
      },
      template: `
        <div>
          <input type="text" v-model="adviceText">
          <button v-on:click="$emit('advice', adviceText)">
            Кликни для получения какого-нибудь совета
          </button>
        </div>
      `
    })
    
    app.mount('#emit-example-argument')
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
  • См. также:

# $forceUpdate

  • Использование:

    Вызывает принудительную перерисовку экземпляра компонента. Обратите внимание, что он не затрагивает все дочерние компоненты, а только сам экземпляр и дочерние компоненты с содержимым подставленным в слот.

# $nextTick

  • Аргументы:

    • {Function} callback (опционально)
  • Использование:

    Откладывает вызов коллбэка до следующего цикла обновления DOM. Используйте его сразу после изменения данных, чтобы дождаться обновления DOM. Аналогичен глобальному nextTick, за исключением того, что контекст this автоматически привязывается к экземпляру, вызвавшему этот метод.

  • Пример:

    createApp({
      // ...
      methods: {
        // ...
        example() {
          // изменяем данные
          this.message = 'changed'
          // DOM ещё не обновлён
          this.$nextTick(function() {
            // теперь DOM обновлён
            // `this` привязан к текущему экземпляру
            this.doSomethingElse()
          })
        }
      }
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • См. также: nextTick