Vue 3.0 实例方法

时间:2022-10-04 01:18:28

#$watch

  • 参数:

  • {string | Function} source

  • {Function | Object} callback

  •  {Object} [options] 

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

  • 返回:{Function} unwatch

  • 用法:

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

  • 示例:

 
  1. const app = Vue.createApp({
  2. data() {
  3. return {
  4. a: 1,
  5. b: 2,
  6. c: {
  7. d: 3,
  8. e: 4
  9. }
  10. }
  11. },
  12. created() {
  13. // 顶层property 名
  14. this.$watch('a', (newVal, oldVal) => {
  15. // 做点什么
  16. })
  17. // 用于监视单个嵌套property 的函数
  18. this.$watch(
  19. () => this.c.d,
  20. (newVal, oldVal) => {
  21. // 做点什么
  22. }
  23. )
  24. // 用于监视复杂表达式的函数
  25. this.$watch(
  26. // 表达式 `this.a + this.b` 每次得出一个不同的结果时
  27. // 处理函数都会被调用。
  28. // 这就像监听一个未被定义的计算属性
  29. () => this.a + this.b,
  30. (newVal, oldVal) => {
  31. // 做点什么
  32. }
  33. )
  34. }
  35. })

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

 
  1. const app = Vue.createApp({
  2. data() {
  3. return {
  4. article: {
  5. text: 'Vue is awesome!'
  6. },
  7. comments: ['Indeed!', 'I agree']
  8. }
  9. },
  10. created() {
  11. this.$watch('article', () => {
  12. console.log('Article changed!')
  13. })
  14. this.$watch('comments', () => {
  15. console.log('Comments changed!')
  16. })
  17. },
  18. methods: {
  19. // 这些方法不会触发侦听器,因为我们只更改了Object/Array的一个property,
  20. // 不是对象/数组本身
  21. changeArticleText() {
  22. this.article.text = 'Vue 3 is awesome'
  23. },
  24. addComment() {
  25. this.comments.push('New comment')
  26. },
  27. // 这些方法将触发侦听器,因为我们完全替换了对象/数组
  28. changeWholeArticle() {
  29. this.article = { text: 'Vue 3 is awesome' }
  30. },
  31. clearComments() {
  32. this.comments = []
  33. }
  34. }
  35. })

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

 
  1. const app = Vue.createApp({
  2. data() {
  3. return {
  4. a: 1
  5. }
  6. }
  7. })
  8. const vm = app.mount('#app')
  9. const unwatch = vm.$watch('a', cb)
  10. // later, teardown the watcher
  11. unwatch()

  • 选项:deep

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

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

  • 选项:immediate

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

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

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

 
  1. // 这会导致报错
  2. const unwatch = vm.$watch(
  3. 'value',
  4. function() {
  5. doSomething()
  6. unwatch()
  7. },
  8. { immediate: true }
  9. )

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

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

  • Option: flush

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

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

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

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

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

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

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

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

#$emit

  • 参数:

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

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

  • 示例:

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

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

 
  1. const app = Vue.createApp({
  2. methods: {
  3. sayHi() {
  4. console.log('Hi!')
  5. }
  6. }
  7. })
  8. app.component('welcome-button', {
  9. template: `
  10. <button v-on:click="$emit('welcome')">
  11. Click me to be welcomed
  12. </button>
  13. `
  14. })
  15. app.mount('#emit-example-simple')

配合额外的参数使用 $emit

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

 
  1. const app = Vue.createApp({
  2. methods: {
  3. showAdvice(advice) {
  4. alert(advice)
  5. }
  6. }
  7. })
  8. app.component('advice-component', {
  9. data() {
  10. return {
  11. adviceText: 'Some advice'
  12. }
  13. },
  14. template: `
  15. <div>
  16. <input type="text" v-model="adviceText">
  17. <button v-on:click="$emit('give-advice', adviceText)">
  18. Click me for sending advice
  19. </button>
  20. </div>
  21. `
  22. })

  • 参考

#$forceUpdate

  • 用法:

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

#$nextTick

  • 参数:

  • {Function} [callback]

  • 用法:

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

  • 示例:

 
  1. Vue.createApp({
  2. // ...
  3. methods: {
  4. // ...
  5. example() {
  6. // modify data
  7. this.message = 'changed'
  8. // DOM is not updated yet
  9. this.$nextTick(function() {
  10. // DOM is now updated
  11. // `this` is bound to the current instance
  12. this.doSomethingElse()
  13. })
  14. }
  15. }
  16. })