vue3的watch监听<与vue2比较>

本文详细介绍了Vue.js中watch监听的使用,包括基本用法、监视指定数据源、多个数据源以及清除监视。通过实例展示了如何监听ref和reactive类型的数据,以及如何在watch中清除无效的异步任务。同时,对比了方法格式和对象格式的watch监听,并指出了各自的优缺点。

watch监听

watch() 函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:

import { watch } from 'vue'

基本用法

const count = ref(0)

// 定义 watch,只要 count 值变化,就会触发 watch 回调
// watch 会在创建时会自动调用一次
watch(() => console.log(count.value))
// 输出 0

setTimeout(() => {
  count.value++
  // 输出 1
}, 1000)

监视指定的数据源

监视 reactive 类型的数据源:

// 定义数据源
const state = reactive({ count: 0 })
// 监视 state.count 这个数据节点的变化
watch(
  () => state.count,
    //newCount新数据,oldCount旧数据
  (newCount,oldCount) => {
    /* ... */
  }
)

监视 ref 类型的数据源:

// 定义数据源
const count = ref(0)
// 指定要监视的数据源
watch(count, (count, prevCount) => {
  /* ... */
})

监视多个数据源

监视 reactive 类型的数据源:

const state = reactive({ count: 0, name: 'zs' })

watch(
  [() => state.count, () => state.name], // Object.values(toRefs(state)),
  ([count, name], [prevCount, prevName]) => {
    console.log(count) // 新的 count 值
    console.log(name) // 新的 name 值
    console.log('------------')
    console.log(prevCount) // 旧的 count 值
    console.log(prevName) // 旧的 name 值
  },
  {
    lazy: true // 在 watch第一次被创建的时候,不执行回调函数中的代码
  }
)

setTimeout(() => {
  state.count++
  state.name = 'ls'
}, 1000)

监视 ref 类型的数据源:

const count = ref(0)
const name = ref('zs')

watch(
  [count, name], // 需要被监视的多个 ref 数据源
  ([count, name], [prevCount, prevName]) => {
    console.log(count)
    console.log(name)
    console.log('-------------')
    console.log(prevCount)
    console.log(prevName)
  },
  {
    lazy: true
  }
)

setTimeout(() => {
  count.value++
  name.value = 'xiaomaolv'
}, 1000)

清除监视

setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:

// 创建监视,并得到 停止函数
const stop = watch(() => {
  /* ... */
})

// 调用停止函数,清除对应的监视
stop()

在 watch 中清除无效的异步任务

有时候,当被 watch 监视的值发生变化时,或 watch 本身被 stop 之后,我们期望能够清除那些无效的异步任务,此时,watch 回调函数中提供了一个 cleanup registrator function 来执行清除的工作。这个清除函数会在如下情况下被调用:

  • watch 被重复执行了
  • watch 被强制 stop

Template 中的代码示例如下

/* template 中的代码 */ <input type="text" v-model="keywords" />

Script 中的代码示例如下

// 定义响应式数据 keywords
const keywords = ref('')

// 异步任务:打印用户输入的关键词
const asyncPrint = val => {
  // 延时 1 秒后打印
  return setTimeout(() => {
    console.log(val)
  }, 1000)
}

// 定义 watch 监听
watch(
  keywords,
  (keywords, prevKeywords, onCleanup) => {
    // 执行异步任务,并得到关闭异步任务的 timerId
    const timerId = asyncPrint(keywords)

    // 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
    onCleanup(() => clearTimeout(timerId))
  },
  // watch 刚被创建的时候不执行
  { lazy: true }
)

// 把 template 中需要的数据 return 出去
return {
  keywords
}

vue2中的watch监听

方法格式的监听

侦听数据变化,在watch节点,要监听谁,就把谁当作方法名

data:{username:''}
watch:{
//监听值username的变化
//newVal是变化后的新值,oldVal是旧值
	username(newVal,oldVal){}
}
<input type="text" v-model="username">
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: '1'
            },
            watch: {
                //本质还是函数,监视谁就把谁作为函数名
                username(newVal, oldVal) {
                    console.log(newVal, oldVal);
                }
            }
        })
    </script>

上面用的都是方法格式的侦听器,有缺点

  • 无法在刚进入页面的时候自动触发(要使用对象格式的immediate选项)
  • 无法深度监听对象内部每个属性的变化(要使用对象格式的deep选项)
对象格式的监听

对象格式的侦听器,使用immediate

        var vm = new Vue({
            el: '#app',
            data: {
                username: ''
            },
            watch: {
                //定义对象格式的侦听器
                username: {
                    //侦听器的处理函数
                    handler(newVal, oldVal) {
                    },
                    //自动立即触发,默认为false
                    immediate: true
                }
            }
        })

对象格式的侦听器,使用deep

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                //用户的信息对象
                info: {
                    username: 'admin'
                }
            },
            watch: {
                //如果侦听对象,对象里面属性的变化不会被侦听到
                info: {
                    handler(newVal) {
                        console.log(newVal);
                    },
                    //开启深度监听
                    deep: true
                }
            }
        })

如果不需要深度监听,想只监听单个属性的变化,则必须包裹一层单引号(直接用方法格式)

'info.username'(newVal){}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的战斗鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值