不习惯的 Vue3 起步三 の computed 和 watch
Posted 空城机
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不习惯的 Vue3 起步三 の computed 和 watch相关的知识,希望对你有一定的参考价值。
计算属性和侦听器
Computed计算属性
在模板内表达式非常简单,如果在模板内放入过多的逻辑会使得模板过重并且难以维护。
示例:
<template>
<div> admin.friends.filter((item)=> if (item.name == '李四') return true else return false; ).length > 0 ? `$admin.name有李四这个朋友`: `$admin.name没有李四这个朋友` </div>
</template>
<script setup lang="ts">
import ref, reactive, onMounted from "vue";
let admin = ref(
name: '张三',
friends: [
name: '李四',
age: 15
]
)
</script>
在上述例子中,div元素中进行判断编写的就过于复杂了,此时模板不再是简单的,必须先看一下,才能意识到结果取决于admin.friend
中是否有李四,如果要在模板中多次包含改计算,template
会更加糟糕
对于任何包含响应式数据的复杂逻辑,都可以使用计算属性
computed: 接收一个回调函数,返回一个通过其他属性经过计算的新值,此新值是通过ref包装过的常量
对于上面的例子,可以使用computed抛出一个计算量
// 传参
let showres = computed(()=>(admin)=>
return admin.friends.filter((item)=>
if (item.name == '李四') return true
else return false;
).length > 0 ? `$admin.name有李四这个朋友`: `$admin.name没有李四这个朋友`
)
在template
中使用<div> showres(admin) </div>
即可显示,并且如果对admin做修改,showres也可以生效修改,这其实与Vue2
中的computed是一样的,只不过写法上有了一些区别
<template>
<div> showres(admin) </div>
<button @click="change">改变</button>
</template>
<script setup lang="ts">
import ref, reactive, onMounted, computed from "vue";
let admin = ...
// 传参
let showres = ...
function change()
admin.value =
name: '王五',
friends: []
</script>
效果:
computed 对比 methods
当然如果写一个methods方法来代替计算属性,也是能够实现相同的效果的,两者之间的区别在于计算属性基于反应依赖关系缓存的,只有相关响应式依赖发生改变时才会重新求值。而方法是每当触发重新渲染时,调用方法将总会再次执行函数。
比如下面:只改变数值t,但是随着渲染刷新,methods方法产生的showres2也会随之改变,而computed因为响应式依赖没有改变,所以不动。
<template>
<div> showres </div>
<div> showres2() </div>
t
<button @click="change">改变</button>
</template>
<script setup lang="ts">
import ref, reactive, onMounted, computed from "vue";
let t = ref(1);
// 传参
let showres = computed(()=>
return new Date()
)
let showres2 = ()=>
return new Date()
function change()
setInterval(()=>
t.value++;
, 1000)
</script>
效果:
使用 computed 会产生一个缓存,所以在性能上比methods更好,不过如果不希望缓存,也可以使用methods。
watch侦听器
watch API 与选项式 API this.$watch (以及相应的 watch 选项) 完全等效
当需要在数据变化时执行异步或开销较大的操作时,使用watch
比使用computed
更有效。
watch有三个参数:
- 一个想要侦听的响应式引用或 getter 函数
- 回调函数
- 监听的配置(可选)
对于监听的对象,ref定义和reactive定义时监听方式也是不同的
对于ref
:
/* watch */
let count1 = ref(10), count2 = ref(20)
watch(count1, (newval, oldval)=>
console.log(newval, oldval)
)
// 监听多个值
watch([count1, count2], (newval, oldval)=>
console.log(newval, oldval)
)
function change()
count1.value++
ref,可以监听单个值,也可以同时监听多个值,第一个参数直接写ref或者ref数组即可。
对于reactive
:
- 如果将reactive对象传入watch,只能监听到新值,对于老值是无法监听的
const state = reactive( count: 0 )
watch(state, (newval, oldval)=>
console.log(newval.count, oldval.count)
)
function change()
state.count++
- 如果想要监听reactive对象中某一属性,要使用
()=> ...
函数的方式,并且这样对于count的改变新值和老值都能监听到
watch(()=>state.count, (newval, oldval)=>
console.log(newval, oldval)
)
- 如果想要监听reactive对象多个属性,可以像之前监听ref时一样使用
[]
const state = reactive( count: 0, age: 1 )
watch([()=>state.count, ()=>state.age], (newval, oldval)=>
console.log(newval, oldval)
)
watchEffect
watchEffect属于对watch的一些补充吧,不过大部分时候还是使用watch就足够了。
watchEffect:
- 不需要手动传入依赖
- 不是lazy初始化执行分析依赖,而watch是lazy的,页面第一次加载不会触发,除非使用
immediate
。watchEffect会在onMounted之前调用 - watchEffect无法获取老值,只能获取新值
- 一些异步操作放里面比watch更合适
- watch的第三个参数是处理副作用的,watchEffect靠第一个参数,watchEffect第二个参数可以设置
onTrigger
、flush
等侦听器行为调试,参考API:https://www.bookstack.cn/read/vue-3.0-zh/5b0a2b746cf872b6.md
示例:
let stop = watchEffect((onInvalidate)=>
console.log(count1.value)
onInvalidate(()=>
// onInvalidate清除副作用
)
)
// 结束watch监听
stop();
PS: 并且watchEffect无法对reactive进行监听,因为无法监测对象内部的变化
以上是关于不习惯的 Vue3 起步三 の computed 和 watch的主要内容,如果未能解决你的问题,请参考以下文章