深度解析Vue3中的computed和watch

一.Vue3中computed用法

         在Vue3的官方文档中,给予的computed的定义是这样的,computed()API接受一个getter函数,返回一个只读属性的响应式ref对象,ref通过暴露getter函数的返回值,它也可以接受一个带有get和set函数的对象来创建一个可写的ref对象。

    1.1computed的只读性

       通过computed得到的对象属性是只读的,得到的对象属性是不可修改的,在如下代码中我通过计算属性得到了一个人的全名,又定义了一个方法来修改通过computed得到的全名


一个人的姓:<input type="text" v-model="firstName"><br>
一个人的名:<input type="text" v-model="lastName"><br>
一个人的姓名:<span>{{ fullName }}</span>
<button @click="changefullName">点击修改全名</button>
let firstName=ref("张");
let lastName=ref("峻豪");
let fullName=computed(()=>{
   return firstName.value+lastName.value;
})
function changefullName(){
    fullName.value='余宇涵'
}

可以看到在上面的图片中,firstName和lastName是通过ref定义的,而fullName是通过computed得到的,fullName的值可以跟着firstName和lastName的值而改变,但是,如果我使用一个方法来直接改变fullName的值,就会出现如下结果:

控制台回给出一个警告,来告诉我们computed中的值为只读的,不可以直接修改。

   1.2修改computed中的值:

      如果我们在使用computed的时候想要修改computed的值,那我们就要用到一个computed中的set方法,具体如下代码所示:

let fullName=computed({
    get:()=>{return firstName.value+lastName.value},
    set:(val)=>{
        console.log('set',val);
    }
})
function changefullName(){
    fullName.value='余宇涵'
}

在上述代码中,我调用了computed内部的get和set方法,get 是用来得到通过计算属性而得到的值,而使用set变 就可以修改通过计算属性而得到的值,当我调用changefullName方法,控制台就会显示这样:

   1.3computed的其他特性:

     computed它是根据他依赖的计算属性的变化而变化的,它和普通的计算函数不同,只要调用普通的计算函数,不管他的参数有没有变化,都会调用普通的计算函数,而computed不同,只有当他依赖的属性发生变化的时候,它才会执行功能。

二.Vue3中的watch方法:

      在vue3的官方文档上给的watch的定义是这样的:侦听一个或者是多个响应式的数据源,并且在数据源发生变化的时候调用所给的回调函数。在实际应用watch的时候主要有以下五种情况:

          2.1监视ref所定义的基本类型的数据:

                这种情况就是当ref定义的基本类型的数据发生改变的时候,就会自动调用所给的回调函数,代码片段如下所示:

  <p>监视ref定义的基本类型{{ sum }}</p>
    <button @click="changeSum">点击改变sum的值</button>
function changeSum(){
    sum.value+=10;
}
watch(sum,(newValue,oldValue)=>{
    console.log('sum的值改变了',newValue,oldValue);
})

在上述代码片段中,watch的回调函数中接受newValue,oldValue两个值,当侦听到定义的sum对象发生改变式,就会调用回调函数,控制台输出如下所示:

       2.2监视ref定义的对象类型的数据

      如果使用watch监听ref定义的对象类型的数据,默认监听的是定义的整个对象,如果想要监听对象中的每一个属性,则要开启深度监听,代码体现如下:

 <p>{{person.name}}</p>
    <p>{{ person.age }}</p>
    <button @click="changeName">修改我的名字</button>
    <button @click="changeAge">修改我的年龄</button>
    <button @click="changeAll">修改我的全部信息</button>
let person=ref({
    name:'张峻豪',
    age:16
})//定义的ref类型的对象
function changeName(){
    person.value.name+='~'
}//修改名字
function changeAge(){
    person.value.age+=1
}//修改年龄
function changeAll(){
    person.value={name:"李菲",age:28}
}//修改整个对象的内容
watch(person,(newValue,oldValue)=>{
    console.log('改变了person的内容',newValue,oldValue);
})//开启监视

在上述的代码片段中,我定义了一个ref类型的person对象,如果是默认监听的话,当我修改person对象里的name和age时,控制台不会打印,也就是说没有监听到对象中属性的变化,只有我修改整个对象的内容时,监听才起作用,控制台的结果如下:

如果我们想要监听到ref定义的对象类型中的每一个属性时,我们要开启深度监听,默认监听的只有在对象内存地址改变的情况下才起作用(也就是生成另一个新的对象),如果我们想要监听到person中的name和age,修改代码如下:

 <p>{{person.name}}</p>
    <p>{{ person.age }}</p>
    <button @click="changeName">修改我的名字</button>
    <button @click="changeAge">修改我的年龄</button>
    <button @click="changeAll">修改我的全部信息</button>
let person=ref({
    name:'张峻豪',
    age:16
})//定义的ref类型的对象
function changeName(){
    person.value.name+='~'
}//修改名字
function changeAge(){
    person.value.age+=1
}//修改年龄
function changeAll(){
    person.value={name:"李菲",age:28}
}//修改整个对象的内容
watch(person,(newValue,oldValue)=>{
    console.log('改变了person的内容',newValue,oldValue);
},{deep:true})//开启深度监听

当我改变person中的name或者age时,控制台结果如下:

修改名字:

修改年龄:

       2.3监听reactive所定义的对象类型:

       当我们使用watch监听reactive定义的对象类型时,侦听器在底层默认开启了深度监听,所以能够监听到对象中每一个属性的值的变化,代码体现如下:

 <p>{{person.name}}</p>
    <p>{{ person.age }}</p>
    <button @click="changeName">修改我的名字</button>
    <button @click="changeAge">修改我的年龄</button>
    <button @click="changeAll">修改我的全部信息</button>
let person=reactive({
    name:'张峻豪',
    age:16
})//定义一个reactive对象
function changeName(){
    person.name+='~'
}//改变person的名字
function changeAge(){
    person.age+=1
}//改变person的年龄
function changeAll(){
   Object.assign(person,{name:"李菲",age:28})
}//使用对象中的方法改变整个对象的值
watch(person,(newValue,oldValue)=>{
    console.log('改变了person对象的内容',newValue,oldValue);
})//开启监听

在上述代码中,当我改变person中的name和age时,侦听器能够监听到这两者的变化

控制台的结果显示监听到了person对象中属性的变化,但是,当我们整体改变person对象的内容时,会发现newValue和oldValue相同

出现上述情况是因为深度监听监听的是地址值变化的情况,而我改变对象的时候只是覆盖了原来对象的值,对象的地址值并没有改变,所以会出现上述情况。

       2.4监听ref或者reactive对象中的非对象属性:

     如果想要监视到ref或者是reactive对象中的非对象属性,就要使用get函数,先得到这个值,对得到的这个值进行监听,代码片段如下

<h2>{{ person.name }}</h2><br>
<h2>{{ person.age }}</h2><br>
<h2>{{ person.car.c1 }}</h2><br>
<h2>{{ person.car.c2 }}</h2><br>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改第一个</button>
<button @click="changeC2">修改第二个</button>
<button @click="changeAll">修改全部</button>
let person=reactive({
    name:"张峻豪",
    age:16,
    car:{
        c1:'自行车',
        c2:'电动车',
    }
})
function changeName(){
    person.name+='~'
}
function changeAge(){
    person.age+=1
}
function changeC1(){
    person.car.c1='宝马'
}
function changeC2(){
    person.car.c2='奥迪'
}
function changeAll(){
    person.car={c1:'红旗',c2:'迈巴赫'}
}
watch(()=>person.car,(newValue,oldValue)=>{
     console.log('car的内容改变了',newValue,oldValue);
},{deep:true})
watch(()=>person.age,(newValue,oldValue)=>{
    console.log('年龄改变了',newValue,oldValue);
})

控制台效果如下:

 

在上述代码中,在侦听器中使用了函数的形式(本质是get函数简写)来监听到对象中的非对象属性,当然了,对象属性也可以使用函数的形式来监听到 ,都使用函数形式来监听可以方便并且保险一些。

      2.5监听多个属性:

当我们想使用监听器监听多个属性时,我们可以在监听器中将要监听的对象放在一个监听数组中,

代码体现如下:

watch([()=>person.age,person.car],(newValue,oldValue)=>{
    console.log('观察改变的内容',newValue,oldValue);
},{deep:true})

把要监听的对象属性放在一个数组中,就可以监听多个对象属性了,由于car的类型时一个对象属性的,所以可以不使用函数的形式来监听。

三.watchEffect

       当我们在实际应用时,会发现我们想要通过监听多个数据的变化来处理下一步逻辑,但是,当我们想要监听的数据比较多时,代码会比较冗余,所以,我们可以使用watchEffect来自动监听我们所要处理逻辑的数据

<h2>水位:{{ hei }}cm</h2>
<h2>水温:{{tem}}℃</h2>
<button @click="changeHei">改变水位</button>
<button @click="changeTem">改变水温</button>
let hei=ref(10)
let tem=ref(20)
function changeHei(){
    hei.value+=10;
}
function changeTem(){
    tem.value+=15;
}
watchEffect(()=>{
    if(hei.value>30||tem.value>60){
        console.log('向服务器发送数据',hei.value,tem.value);
    }
})

   其实,当我们使用watchEffect来监听数据时,就相当于开启来watch里的immediate,然后再根据下面的逻辑处理来监听所需要的数据,使用watchEffect时,在数据量比较多,并且逻辑所依赖的数据较多时,使代码更加简洁优雅。

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值