Vue 3.0 实例方法

#$watch

  • 参数:

  • {string | Function} source

  • {Function | Object} callback

  • {Object} [options]

  • {boolean} deep
  • {boolean} immediate
  • {string} flush

  • 返回:{Function} unwatch

  • 用法:

侦听组件实例上的响应式 property 或函数计算结果的变化。回调函数得到的参数为新值和旧值。我们只能将顶层的 datapropcomputed property 名作为字符串传递。对于更复杂的表达式,用一个函数取代。

  • 示例:

  const app = Vue.createApp({
    data() {
      return {
        a: 1,
        b: 2,
        c: {
          d: 3,
          e: 4
        }
      }
    },
    created() {
      // 顶层property 名
      this.$watch('a', (newVal, oldVal) => {
        // 做点什么
      })

  
      // 用于监视单个嵌套property 的函数
      this.$watch(
        () => this.c.d,
        (newVal, oldVal) => {
          // 做点什么
        }
      )

  
      // 用于监视复杂表达式的函数
      this.$watch(
        // 表达式 `this.a + this.b` 每次得出一个不同的结果时
        // 处理函数都会被调用。
        // 这就像监听一个未被定义的计算属性
        () => this.a + this.b,
        (newVal, oldVal) => {
          // 做点什么
        }
      )
    }
  })

当侦听的值是一个对象或者数组时,对其属性或元素的任何更改都不会触发侦听器,因为它们引用相同的对象/数组:

  const app = Vue.createApp({
    data() {
      return {
        article: {
          text: 'Vue is awesome!'
        },
        comments: ['Indeed!', 'I agree']
      }
    },
    created() {
      this.$watch('article', () => {
        console.log('Article changed!')
      })

  
      this.$watch('comments', () => {
        console.log('Comments changed!')
      })
    },
    methods: {
      // 这些方法不会触发侦听器,因为我们只更改了Object/Array的一个property,
      // 不是对象/数组本身
      changeArticleText() {
        this.article.text = 'Vue 3 is awesome'
      },
      addComment() {
        this.comments.push('New comment')
      },

  
      // 这些方法将触发侦听器,因为我们完全替换了对象/数组
      changeWholeArticle() {
        this.article = { text: 'Vue 3 is awesome' }
      },
      clearComments() {
        this.comments = []
      }
    }
  })

$watch 返回一个取消侦听函数,用来停止触发回调:

  const app = Vue.createApp({
    data() {
      return {
        a: 1
      }
    }
  })

  
  const vm = app.mount('#app')

  
  const unwatch = vm.$watch('a', cb)
  // later, teardown the watcher
  unwatch()

  • 选项:deep

为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。

  vm.$watch('someObject', callback, {
    deep: true
  })
  vm.someObject.nestedValue = 123
  // callback is fired

  • 选项:immediate

在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调:

  vm.$watch('a', callback, {
    immediate: true
  })
  // 立即以 `a` 的当前值触发 `callback`

注意,在带有 immediate 选项时,你不能在第一次回调时取消侦听给定的 property。

  // 这会导致报错
  const unwatch = vm.$watch(
    'value',
    function() {
      doSomething()
      unwatch()
    },
    { immediate: true }
  )

如果你仍然希望在回调内部调用一个取消侦听的函数,你应该先检查其函数的可用性:

  let unwatch = null

  
  unwatch = vm.$watch(
    'value',
    function() {
      doSomething()
      if (unwatch) {
        unwatch()
      }
    },
    { immediate: true }
  )

  • Option: flush

flush选项允许更好地控制回调的时间。它可以设置为prepostsync

默认值为pre,它指定在呈现之前应调用回调。这允许回调在模板运行之前更新其他值。

post可用于将回调延迟到呈现之后。如果回调需要通过$refs访问更新的DOM或子组件,则应使用此选项。

如果flush设置为sync,则只要值发生更改,就会同步调用回调。

对于prepost,回调都使用队列进行缓冲。回调只会添加到队列一次,即使关注的值更改多次。临时值将被跳过,不会传递给回调。

缓冲回调不仅可以提高性能,而且有助于确保数据一致性。在执行数据更新的代码完成之前,不会触发监视程序。

sync观察者应该谨慎使用,因为他们没有这些好处。


有关`flush`的详细信息,请参见[效果刷新计时](https://www.sxiaw.com/vuejs3/vuejs3-35qs3f4h.html)。

#$emit

  • 参数:

  • {string} eventName
  • [...args]

触发当前实例上的事件。附加参数都会传给监听器回调。

  • 示例:

只配合一个事件名使用 $emit:

  <div id="emit-example-simple">
    <welcome-button v-on:welcome="sayHi"></welcome-button>
  </div>

  const app = Vue.createApp({
    methods: {
      sayHi() {
        console.log('Hi!')
      }
    }
  })

  
  app.component('welcome-button', {
    template: `
      <button v-on:click="$emit('welcome')">
        Click me to be welcomed
      </button>
    `
  })

  
  app.mount('#emit-example-simple')

配合额外的参数使用 $emit

  <div id="emit-example-argument">
    <advice-component v-on:give-advice="showAdvice"></advice-component>
  </div>

  const app = Vue.createApp({
    methods: {
      showAdvice(advice) {
        alert(advice)
      }
    }
  })

  
  app.component('advice-component', {
    data() {
      return {
        adviceText: 'Some advice'
      }
    },
    template: `
      <div>
        <input type="text" v-model="adviceText">
        <button v-on:click="$emit('give-advice', adviceText)">
          Click me for sending advice
        </button>
      </div>
    `
  })

  • 参考

#$forceUpdate

  • 用法:

迫使组件实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

#$nextTick

  • 参数:

  • {Function} [callback]

  • 用法:

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

  • 示例:

Vue.createApp({
  // ...
  methods: {
    // ...
    example() {
      // modify data
      this.message = 'changed'
      // DOM is not updated yet
      this.$nextTick(function() {
        // DOM is now updated
        // `this` is bound to the current instance
        this.doSomethingElse()
      })
    }
  }
})