Vue3中watch的value问题

前言

在Vue3中,定义响应式数据有两种方式,第一种是ref,第二种是reactive。在使用监视属性的时候,我们可能会监视普通类型的数据(也就是ref定义的),也可能会监视对象或者数组类型的数据。(也就是reactive定义的,当然也可以是ref定义的)

之前在Vue2与Vue3响应式的详解与对比博客中介绍过ref和reactive的用法及区别,以及为什么要用到value。本篇博客在此基础上阐述,watch检测数据的时候,要不要加value的这个问题。

一,ref和reactive的简单复习

这一节是对ref和reactive的简单复习,如果要深层次的学习以及知晓原理可以看上面那一篇链接博客。

1.ref函数

我们先来看一个ref定义的数据答应出来是个什么,见下面代码:

<template>
    <div>学校名称: {
    
    {
    
     school }}</div>
    <button @click="school = '家里蹲大学'">修改学校名称</button>
</template>

<script>
import {
    
    ref, reactive, watch} from 'vue'
export default {
    
    
    name: 'App',
    setup() {
    
    
        let school = ref('湖北师范大学')
        watch(school, (newValue, oldValue) => {
    
    
            console.log('school被修改');
            console.log(school)
        })
        return {
    
    
            school
        }
    }
}
</script>

效果:
在这里插入图片描述
可以看到最后得到的是一个RefImpt:引入对象的实现对象的实例对象,简称引用对象。使用时,模板语法中可以省略value,函数中需要使用value进行修改。

ref实现响应式的原理和Vue2中实现响应式的原理是一样的,都是通过Object.defintProperty来实现的。

1.2 reactive函数

reactive函数用作对象及数组类型的数据。请看以下代码:

<template>
    <div>学校名称:{
    
    {
    
     school }}</div>
    <button @click="school = '家里蹲大学'">修改学校名称</button>
    <div>姓名: {
    
    {
    
     person.name }}</div>
    <div>工作名称: {
    
    {
    
     person.job.type }}</div>
    <div>工作薪水: {
    
    {
    
     person.job.salary }}</div>
    <button @click="person.job.salary = '100k'">修改薪水</button>
</template>

<script>
import {
    
     ref, reactive, watch } from 'vue'
export default {
    
    
    name: 'App',
    setup() {
    
    
        let school = ref('湖北师范大学')
        let person = reactive({
    
    
            name: '巧克力小猫猿',
            job: {
    
    
                type: '前端开发工程师',
                salary: '90k'
            }
        })

        watch(person, (newValue, oldValue) => {
    
    
            console.log('person被更改')
            console.log(person)
        })


        return {
    
     school, person }
    }
}

效果:
在这里插入图片描述
对于用reactive函数定义的对象类型的数据,内部原理是检测Proxy实例对象。所以在书写是时候不需要value,模板语法中也不需要value,并且可以深度监视。

1.3 用ref定义对象类型数据不用reactive

如下面代码:

扫描二维码关注公众号,回复: 14974311 查看本文章
<template>
    <div>学校名称:{
    
    {
    
     school }}</div>
    <button @click="school = '家里蹲大学'">修改学校名称</button>
    <div>姓名: {
    
    {
    
     person.name }}</div>
    <div>工作名称: {
    
    {
    
     person.job.type }}</div>
    <div>工作薪水: {
    
    {
    
     person.job.salary }}</div>
    <button @click="look">点击查看person</button>
</template>

<script>
import {
    
     ref, reactive, watch } from 'vue'
export default {
    
    
    name: 'App',
    setup() {
    
    
        let school = ref('湖北师范大学')
        let person = ref({
    
    
            name: '巧克力小猫猿',
            job: {
    
    
                type: '前端开发工程师',
                salary: '90k'
            }
        })

        function look() {
    
    
            console.log(person)
        }
        return {
    
     school, person, look}
    }
}
</script>

效果如下:
在这里插入图片描述
可以看出,如果ref遇到一个对象类型的数据类型,会求助reactive。因为检测Proxy实例对象,是由reactive来监测到。而reactive是深层次的,所所以能够检测到Proxy内部的内容。

二,watch的value问题

2.1 ref

首先遇到ref,我们脑海中的原则是,模板语法中不用value,js中操作数据需要带上value。

在watch中,先说结论,如果要检测一个普通类型的数据,不需要value。如果检测对象类型的数据需要加value

2.1.1 普通类型数据

先说普通类型数据,我们现在以一个例子来说明,如下代码:

<template>
    <div>违规次数: {
    
    {
    
     sum }}</div>
    <button @click="sum++">违规次数加1</button>
    <div>姓名: {
    
    {
    
     person.name }}</div>
    <div>工作名称: {
    
    {
    
     person.job.type }}</div>
    <div>工作薪水: {
    
    {
    
     person.job.salary }}</div>
    <button @click="person.job.salary = '100k'">修改薪水</button>
</template>

<script>
import {
    
     ref, reactive, watch } from 'vue'
export default {
    
    
    name: 'App',
    setup() {
    
    
        let sum = ref(0)
        let person = reactive({
    
    
            name: '巧克力小猫猿',
            job: {
    
    
                type: '前端开发工程师',
                salary: '90k'
            }
        })
        //监视sum
        watch(sum, (newValue, oldValue) => {
    
    
            console.log('sum被检测了')
            console.log(sum)
        })


        return {
    
     person, sum}
    }
}
</script>

我们点击sum按钮后,sum这个引用对象被监测了
在这里插入图片描述
但是如果监测的是sum.value:
在这里插入图片描述
无法正常运行:
在这里插入图片描述
原因:sum加一后值为1,我们监测的是sum的结构,而不是1这个数字。所以,在监视ref定义的普通类型数据时,不用加value。

2.1.2 对象类型数据

再说ref定义的对象类型数据被监视的情况。请看下面代码:

<template>
    <div>违规次数: {
    
    {
    
     sum }}</div>
    <button @click="sum++">违规次数加1</button>
    <div>姓名: {
    
    {
    
     person.name }}</div>
    <div>工作名称: {
    
    {
    
     person.job.type }}</div>
    <div>工作薪水: {
    
    {
    
     person.job.salary }}</div>
    <button @click="person.job.salary = '100k'">修改薪水</button>
</template>

<script>
import {
    
     ref, reactive, watch } from 'vue'
export default {
    
    
    name: 'App',
    setup() {
    
    
        let sum = ref(0)
        let person = ref({
    
    
            name: '巧克力小猫猿',
            job: {
    
    
                type: '前端开发工程师',
                salary: '90k'
            }
        })
        //监视sum
        // watch(sum.value, (newValue, oldValue) => {
    
    
        //     console.log('sum被检测了')
        //     console.log(sum)
        // })

        //监视对象类型
        watch(person, (newValue, oldValue) => {
    
    
            console.log('person被监视')
            console.log(person)
        })

        return {
    
     person, sum}
    }
}
</script>

当我改变薪水时候没办法正常运行。但是一旦我加上value:
在这里插入图片描述
可以正常运行:
在这里插入图片描述
因为对象类型的数据经过ref函数加工会变成引用对象,而该对象的value是Proxy类型的。所以我们如果需要监视Proxy对象中的数据则需要监视的是,person.value的结构。

2.1.3 另一种方式

经过了上面的讲解,应该不难开出,对象类型的数据之所以要加value,是因为我们要监视的是对象中的Proxy对象中的属性。

那我们不妨开启watch的深度监视,同样可以解决问题。
在这里插入图片描述
在这里插入图片描述

2.2 reactive

reactive在监视的时候不需要value。前面复习过,reactive会自动帮我们加上value。并且reactive是深度监视的。它可以窥视对象内部的对象。所以我们只需要监视Proxy对象即可。

三,总结

1.watch中,若监视的是普通类型的数据,不可带value,因为我们检测的是该数据的结构而不是数字。
2.监测ref函数加工的对象时,需要加value,因为使用ref来定义对象,ref是需要求助reactive的,因为reactive可以检测Proxy实例对象,是深层次的。
3.检测ref函数加工的对象还有另一种方法,那就是开启deep的深度监视。
4.监测reactive加工的对象时不需要value,因为reactive是通过Proxy拦截对象中属性的变化。而且reactive的监测是深层次的。

不清楚的小伙伴可以去翻看前面的链接文章,里面有详细的原理讲解。

后记

以上内容,如果存在问题希望读者朋友批评指正!

感谢您的阅读,欢迎关注,后续会带来更多深层次的内容!

猜你喜欢

转载自blog.csdn.net/zxdznyy/article/details/129304619