Vue3 watch和watchEffect

<template>
    <div>
        <p>count1: {{ count1 }} -- count2: {{ count2 }}</p>
        <button @click="addCount1">count1+1</button>
        <button @click="multiplyCount2">count2 * 2</button>
    </div>
    -----------
    <div>
        <div>姓名: {{ person.name }}</div>
        <div>年龄: {{ person.age }}</div><br>
        <div>车辆信息<br>
            <div>品牌: {{ person.car.brand }}</div>
            <div>颜色: {{ person.car.type.color }}</div>
            <div v-if="person && person.car">配置:
                <ul>
                    <li v-for="config in person.car.type.configs" :key="config">{{ config }}</li>
                </ul>
            </div>
        </div>
        <button @click="addAge">age+1</button>
        <button @click="changeBrand">changeBrand</button>
        <button @click="changeColor">changeColor</button>
        <button @click="addConfigs">addConfigs</button>
    </div>
</template>

<script>
import { reactive, ref, watch, watchEffect } from 'vue';

export default {
    name: 'WatchCom',
    setup() {
        const count1 = ref(0)
        const count2 = ref(1)
        const addCount1 = () => {
            count1.value++
        }
        const multiplyCount2 = () => {
            count2.value *= 2
        }

        // 1.侦听ref数据(单个)
        // 注意:1)直接侦听count1,不用.value      2)newVal、oldVal正常
        watch(count1, (newVal, oldVal) => {
            console.log('新count', newVal);
            console.log('旧count', oldVal);
        })
        // 2.侦听ref数据(多个)
        // 注意:1)以数组形式作为参数      2)newVal、oldVal正常
        watch([count1, count2], (newVal, oldVal) => {
            console.log('新数组', newVal);
            console.log('旧数组', oldVal);
        })

        // ---------------------------------------

        const person = reactive({
            name: 'zs',
            age: 18,
            car: {
                brand: 'benz',
                type: {
                    color: 'red',
                    configs: ['天窗', '倒车影像', '座椅加热']
                }
            }
        })
        const addAge = () => {
            person.age++
        }
        const changeBrand = () => {
            person.car.brand += '!'
        }
        const changeColor = () => {
            person.car.type.color += '#'
        }
        const addConfigs = () => {
            person.car.type.configs.push('新配置')
        }

        // 3.侦听reactive数据

        // 3.1直接侦听reactive对象
        // 注意:1)直接将reactive作为侦听参数,侦听器会自动启用深层模式
        //      2)若以函数形式侦听reactive对象,则要开启深度侦听,否则侦听无效
        //      3)newVal正常,但oldVal异常(指向同一个对象)

        // 写法1
        // watch(person, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // })

        // 写法2
        // watch(() => person, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // }, { deep: true })

        // 3.2侦听reactive对象中的某个属性(简单数据类型)
        // 注意:1)需要以函数形式作为参数,只侦听当前数据(深层不会侦听)
        //      2)newVal、oldVal正常
        // watch(() => person.age, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // })

        // 3.3侦听reactive对象中的某个属性(引用数据类型/复杂数据类型)
        // 注意:1)需要以函数形式作为参数
        //      2)需要开启深层侦听{ deep: true }
        //      3)newVal正常,但oldVal异常(指向同一个对象)
        // watch(() => person.car, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // }, { deep: true })

        // 3.4侦听reactive对象中的某个属性(引用数据类型/复杂数据类型)的属性(简单数据类型)
        // 注意:1)需要以函数形式作为参数
        //      2)newVal、oldVal正常
        // watch(() => person.car.brand, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // })

        // 3.5侦听reactive对象中的某个属性(引用数据类型/复杂数据类型)的属性(引用数据类型)
        // 注意:1)需要以函数形式作为参数
        //      2)需要开启深层侦听{ deep: true }
        //      3)newVal正常,但oldVal异常(指向同一个对象)
        // watch(() => person.car.type, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // }, { deep: true })

        // 3.6侦听reactive对象中的某个属性(引用数据类型/复杂数据类型)的属性(引用数据类型)的属性(简单数据类型)
        // 注意:1)需要以函数形式作为参数
        //      2)newVal、oldVal正常
        // watch(() => person.car.type.color, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // })

        // 3.5侦听reactive对象中的某个属性(引用数据类型/复杂数据类型)的属性(引用数据类型)的属性(引用数据类型)
        // 注意:1)需要以函数形式作为参数
        //      2)需要开启深层侦听{ deep: true }
        //      3)newVal正常,但oldVal异常(指向同一个对象)
        // watch(() => person.car.type.configs, (newVal, oldVal) => {
        //     console.log('新', newVal);
        //     console.log('旧', oldVal);
        // }, { deep: true })

        // 总结:
        // 1.直接侦听reactive对象,默认开启深度侦听
        // 2.侦听简单数据类型,不需要深度侦听;侦听引用数据类型,需要深度侦听
        // 3.深度侦听需要遍历侦听对象中所有嵌套属性,当用于大型数据结构时,开销很大,谨慎使用


        // 4.watchEffect
        // watchEffect(立即执行的回调函数, options?)
        // 用途:只要是在回调函数中出现的变量,就会侦听(简单数据类型才有效!!!!!)
        watchEffect(() => {
            console.log(person.age);    // 有效
            console.log(person.car);
            console.log(person.car.brand);    // 有效
            console.log(person.car.type);
            console.log(person.car.type.color);    // 有效
            console.log(person.car.type.configs);
        })


        // 5.回调的触发时机:默认情况下,watch/watchEffect的回调函数是在Vue组件更新前被调用
        // 意味着,在回调中访问的DOM是更新前的状态
        // 若想在回调中访问更新后的DOM,配置 { flush:'post' }

        watch(source, callback,{ flush:'post' })

        // watchEffect有两种写法:
        // 第一种:
        watchEffect(callback,{ flush:'post' })
        // 第二种:
        import { watchPostEffect } from 'vue'
        watchPostEffect(()=>{
            /* 在 Vue 更新后执行 */
        })



        return { count1, count2, addCount1, multiplyCount2, person, addAge, changeBrand, changeColor, addConfigs }
    }
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值