setup中 watch
第一步: 引入watch
第二步使用
侦听器数据源可以是一个具有返回值的 getter 函数,也可以直接是一个 ref:
例如
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
监听多个数据
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
侦听基本数据类型时候
<template>
<div class="home">
<h2>{{counter}}</h2>
<button @click="changeCounter">改变Counter</button>
<h2>{{user.name}}</h2>
<button @click="changeUserName">改变名字</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue'
export default {
setup() {
const counter = ref(0)
function changeCounter() {
counter.value++
}
const user = reactive({
name: '张三',
age: 18,
})
function changeUserName() {
user.name = '李四'
}
watch(counter,(newVal,oldVal)=>{
console.log('newVal-----', newVal)
console.log('oldVal-----', oldVal)
})
return {
counter,
user,
changeUserName,
changeCounter,
}
},
}
</script>
当我们点击修改counter时可以发现控制台打印如下信息
//点击第一次
newVal----- 1
oldVal----- 0
//点击第二次
newVal----- 2
oldVal----- 1
侦听对象的时候
<template>
<div class="home">
<h2>{{counter}}</h2>
<button @click="changeCounter">改变Counter</button>
<h2>{{user.name}}</h2>
<button @click="changeUserName">改变名字</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue'
export default {
data() {
return {
message: 'hello-word',
}
},
setup() {
const counter = ref(0)
function changeCounter() {
counter.value++
}
const user = reactive({
name: '张三',
age: 18,
})
function changeUserName() {
user.name = '李四'
}
watch(user, (newVal, oldVal) => {
console.log('newVal-----', newVal)
console.log('oldVal-----', oldVal)
})
return {
counter,
user,
changeUserName,
changeCounter,
}
},
watch: {
message(newVal, oldVal) {},
},
}
</script>
打印信息
newVal----- Proxy {name: '李四', age: 18}
oldVal----- Proxy {name: '李四', age: 18}
侦听多个数据源
<template>
<div class="home">
<h2>{{person1.name}}</h2>
<h2>{{person2.name}}</h2>
</div>
</template>
<script>
import { ref, reactive, watch, watchEffect } from 'vue'
export default {
setup() {
const person1 = reactive({
name: '张三',
})
const person2 = reactive({
name: '李四',
})
watch([person1, person2], ([newValp1, newValp2], [oldValp1, oldValp2]) => {
console.log('person1的新值--------', newValp1)
console.log('person2的新值--------', newValp2)
console.log('------------------------------')
console.log('person1的旧值--------', oldValp1)
console.log('person2的旧值--------', oldValp2)
})
setTimeout(() => {
person1.name = '张三changed'
person2.name = '李四changed'
}, 500)
setTimeout(() => {
person1.name = '张三changed2'
person2.name = '李四changed2'
}, 3000)
return {
person1,
person2,
}
},
}
</script>
// 第一次改变
person1的新值-------- Proxy {name: '张三changed'}
person2的新值-------- Proxy {name: '李四changed'}
------------------------------
person1的旧值-------- Proxy {name: '张三changed'}
person2的旧值-------- Proxy {name: '李四changed'}
//第二次改变
person1的新值-------- Proxy {name: '张三changed2'}
person2的新值-------- Proxy {name: '李四changed2'}
------------------------------
person1的旧值-------- Proxy {name: '张三changed2'}
person2的旧值-------- Proxy {name: '李四changed2'}
这是是两个数据源同时发生改变,但是watch函数只是触发了一次,并且只能获取到改变之后的值,不能获取改变之前的值
直接侦听user的时候,会发现 打印的都是新值,不会打印到旧的值,因此要侦听到对象某一个属性变化要用另一种写法
watch(
() => user.name,
(newVal, oldVal) => {
console.log('newVal-----', newVal)
console.log('oldVal-----', oldVal)
}
)
打印信息如下,这种就可以观察到改变前后的值
newVal----- 李四
oldVal----- 张三
setup 中的watchEffect
第一步:引入
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
- 立即执行,没有惰性,页面的首次加载就会执行。
- 自动检测内部代码,代码中有依赖 便会执行
- 不需要传递要侦听的内容 会自动感知代码依赖,不需要传递很多参数,只要传递一个回调函数
- 不能获取之前数据的值 只能获取当前值
- 一些=异步的操作放在这里会更加合适
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
例如
<template>
<div class="home">
<h2>{{counter}}</h2>
<button @click="changeCounter">改变Counter</button>
<h2>{{user.name}}</h2>
<button @click="changeUserName">改变名字</button>
</div>
</template>
<script>
import { ref, reactive, watch, watchEffect } from 'vue'
export default {
setup() {
const counter = ref(0)
function changeCounter() {
counter.value++
}
const user = reactive({
name: '张三',
age: 18,
})
function changeUserName() {
user.name = '李四'
}
watchEffect(() => console.log(user.name))
return {
counter,
user,
changeUserName,
changeCounter,
}
},
}
</script>
控制台就一开始就会打印
张三
// 点击修改名字btn 后就会打印
李四
区别
- watchEffect 不需要指定监听的属性,自动收集依赖,只要在回调中引用到了响应式的属性,只要这些属性发生改变,回调就会执行
- watch只能供听指定的属性,做出 回调函数的执行,vue3开始后可以侦听多个
- watch可以获取到新值和旧值, watcheffect拿不到,只能拿到改变之后的值
- watchEffect在组件初始化的时候就会自动执行一次。用来收集依赖,watch第一次页面展示的时候不会执行,只有数据变化的时候才会执行
相同点
watch 与 watchEffect 在手动停止侦听、清除副作用 (将 onInvalidate 作为第三个参数传递给回调)、刷新时机和调试方面有相同的行为。
侦听器的取消 watch 取消侦听器用法相同
const stop = watchEffect(() => {
console.log(nameObj.name)
setTimeout(() => {
stop()
}, 5000)
})
const stop1 = watch([() => nameObj.name, () => nameObj.name], ([curName, curEng], [prevName, curEng]) => {
console.log(curName, curEng, '----', prevName, curEng)
setTimeout(() => {
stop1()
}, 5000)
})