Vue3 watch
从三个方面来解释watch
1、监听 reactive 内部数据
2、监听 ref 数据
3、监听普通数据
一、监听 reactive 内部数据
注意 1:监听 reactive 内部数据时,强制开启了深度监听,且配置无效
注意2:监听对象的时候 newValue 和 oldValue 是全等的
<template>
<p>{{ obj.hobby.eat }}</p>
<button @click="obj.hobby.eat = '面条'">click</button>
</template>
<script>
import { watch, reactive } from 'vue'
export default {
name: 'App',
setup() {
const obj = reactive({
name: 'ifer',
hobby: {
eat: '西瓜',
},
})
watch(obj, (newValue, oldValue) => {
// 注意1:监听对象的时候,新旧值是相等的
// 注意2:强制开启深度监听,配置无效
console.log(newValue === oldValue) // true
})
return { obj }
},
}
</script>
注意 3:一个reactive中的对象也将会是一个reactive类型的数据
<template>
<p>{{ obj.hobby.eat }}</p>
<button @click="obj.hobby.eat = '面条'">click</button>
</template>
<script>
import { watch, reactive, isReactive } from 'vue'
export default {
name: 'App',
setup() {
const obj = reactive({
name: 'ifer',
hobby: {
eat: '西瓜',
},
})
// reactive 的【内部对象】也是一个 reactive 类型的数据
// console.log(isReactive(obj.hobby))
watch(obj.hobby, (newValue, oldValue) => {
console.log(newValue === oldValue) // true
})
return { obj }
},
}
</script>
注意 4:对 reactive 自身的修改则不会触发监听。
<template>
<p>{{ obj.hobby.eat }}</p>
<button @click="obj.hobby = { eat: '面条' }">click</button>
</template>
<script>
import { watch, reactive } from 'vue'
export default {
name: 'App',
setup() {
const obj = reactive({
name: 'ifer',
hobby: {
eat: '西瓜',
},
})
watch(obj.hobby, (newValue, oldValue) => {
// obj.hobby = { eat: '面条' }
console.log('对 reactive 自身的修改不会触发监听')
})
return { obj }
},
}
</script>
二、监听 ref 内部数据
1、监听一个 ref 数据
(监听 ref 数据 age,会触发后面的回调,不需要 .value)
<template>
<p>{{ age }}</p>
<button @click="age++">click</button>
</template>
<script>
import { watch, ref } from 'vue'
export default {
name: 'App',
setup() {
const age = ref(18)
// 监听 ref 数据 age,会触发后面的回调,不需要 .value
watch(age, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { age }
},
}
</script>
2、监听多个 ref 数据
<template>
<p>age: {{ age }} num: {{ num }}</p>
<button @click="handleClick">click</button>
</template>
<script>
import { watch, ref } from 'vue'
export default {
name: 'App',
setup() {
const age = ref(18)
const num = ref(0)
const handleClick = () => {
age.value++
num.value++
}
// 数组里面是 ref 数据
watch([age, num], (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { age, num, handleClick }
},
}
</script>
3、watch监听 ref 数据默认是浅监听(默认监听的只是第一层)
那么如果我想监听到对象中的属性的话,可以用以下3种方法
3.1、深度监听
watch(
obj,
(newValue, oldValue) => {
console.log(newValue, oldValue)
console.log(newValue === oldValue)
},
{
//可以使用deep来深度监听
deep: true,
}
)
3.2、直接修改那一层
<template>
<div>
<p>eat:{{ obj.hobby.eat}}</p>
<button @click="obj = { hobby: {eat: '🍜' } }">面条</button>
</div>
</template>
<script>
import { watch, ref, reactive } from 'vue';
export default {
setup() {
const obj = ref({
hobby: {
eat: '西瓜',
},
})
// !watch 监听 ref 类型数据,默认监听的只是第一层,谁是第一层?obj.value 才是一层
watch(obj, () => {
console.log(1)
})
return {obj}
}
}
</script>
<style lang="scss" scoped>
</style>
3.3、监听 ref 中的对象
因为 ref 包裹的如果是一个对象,对象内部的复杂数据类型其实是一个 reactive 类型的数据。当然,这样做的前提是要监听的对象是被内部对象包裹的状态。
<template>
<div>
<p>eat:{{ obj.hobby.eat}}</p>
<button @click="obj.hobby.eat = '🍜'">面条</button>
<button @click="obj.hobby = { eat: '🍜' }">面条2</button>
</div>
</template>
<script>
import { watch, ref, reactive, isReactive } from 'vue';
export default {
setup() {
const obj = ref({
hobby: {
eat: '西瓜',
info: {
address: '河南'
}
},
})
// ref 包裹的如果是一个对象,对象内部的复杂数据类型其实是一个 reactive 类型的数据
// console.log(isReactive(obj.value.hobby))
// 其实现在监听的是一个 reactive 类型数据,就符合监听 reactive 数据的特点
watch(obj.value.hobby, () => {
console.log(1)
})
return {obj}
}
}
</script>
<style lang="scss" scoped>
</style>
三、监听普通对象
这里的普通对象是指除了 ref 和 reactive的数据类型
// 直接监听普通对象,需要在被监听的普通对象前面加上一个函数才可以监听,否则会报错
watch(() => obj.hobby.eat, (newValue, oldValue) => {
console.log(1);
})