vue3中计算属性与监听的使用(setup函数和setup语法糖两版)
一、计算属性
- 计算属性可以帮我们将数据转换成需要展示的数据格式,不必在模板中编写大量的表达式进行处理。
- computed()方法可以传一个
函数
将结果return出去
setup函数版本
<template>
<div class="box">
<button @click="num++">添加</button>
<div>单价:{{ price }}¥</div>
<div>数量:{{ num }}¥</div>
<div>总价:{{ total }}</div>
</div>
</template>
<script>
// 引入
import { reactive, toRefs,computed } from 'vue';
export default {
setup() {
const data = reactive({
num: 0,
price: 10
})
// 引入后可直接使用computed()
// 必须有返回值,通过定义变量接收
const total = computed(() => {
// 计算处理总价并return出去
return data.num * data.price + '¥'
})
// 需要将变量返回出去,否则页面无法使用
return {
...toRefs(data),
total
}
},
}
</script>
<style scoped lang="scss"></style>
setup语法糖版本
<template>
<div class="box">
<button @click="data.num++">添加</button>
<div>单价:{{ data.price }}</div>
<div>数量:{{ data.num }}</div>
<div>总价:{{ total }}</div>
</div>
</template>
<script setup>
// 引入
import { reactive,computed } from 'vue';
const data = reactive({
num: 0,
price: 10
})
// 引入后可直接使用computed()
// 必须有返回值,通过定义变量接收,页面可直接使用变量
const total = computed(() => {
return data.num * data.price
})
</script>
<style scoped lang="scss"></style>
修改计算属性
- 计算属性的值默认为只读
- computed()方法也可以传一个
对象
,实现这个对象的get和set方法,以此实现对计算属性的使用和修改 此处演示setup语法糖版本,setup函数同理,不做过多演示
。
<template>
<div class="box">
<button @click="data.num++">添加</button>
<div>单价:{{ data.price }}</div>
<div>数量:{{ data.num }}</div>
<div>总价:{{ total }}</div>
<button @click="handleTotal">添加10个</button>
</div>
</template>
<script setup>
// 引入
import { reactive, computed, } from 'vue';
const data = reactive({
num: 0,
price: 10
})
// 引入后可直接使用computed()
// 必须有返回值,通过定义变量接收,页面可直接使用变量
const total = computed({
// get返回计算属性结果
get: () => {
return data.num * data.price
},
// set可使用传入参数
set: (value) => {
console.log(value)
return data.num = value
}
})
// 通过事件修改计算属性结果
const handleTotal = () => {
total.value = data.num + 10
}
</script>
<style scoped lang="scss"></style>
二、监听(侦听器)
- watch用来监听数据的响应式变化.获取数据变化前后的值
- 可通过不同方式分别对单个数据、多个数据、数据某个属性、首次监听等多个场景进行不同的逻辑处理
- watch(),第一个参数为监听源,第二个参数为监听回调
- 在监听回调中有两个参数,第一个为新值,第二个为旧值
普通监听
<template>
<div class="box">
<div><input type="text" placeholder="请输入" v-model="name"></div>
<div><input type="text" placeholder="请输入" v-model="age"></div>
<button @click="sexChange">变性别</button>
<button @click="hobbyChange">改爱好</button>
</div>
</template>
<script setup>
// 引入
import { ref, reactive,watch } from 'vue';
const data = reactive({
sex: '男',
tel:15612345678,
hobby: ['吃', '喝', '玩', '乐']
})
const name = ref('张三')
const age = ref('18')
const sexChange=()=>{
data.sex=='男'?data.sex='女':data.sex='男'
}
const hobbyChange=()=>{
data.hobby.pop()
}
// 引入监听后通过watch(),第一个参数为监听源,第二个参数为监听回调
// 在监听回调中有两个参数,第一个为新值,第二个为旧值
watch(name, (newData, oldData) => {
console.log(newData, oldData);
})
</script>
<style scoped lang="scss"></style>
监听多个
- 当有多个数据需要同时监听时,可以通过数组的方式进行监听
newData
和oldData
此时也为数组
watch([name,age], (newData, oldData) => {
// 返回的数据是数组
console.log(newData, oldData);
})
首次监听
- 通过添加
immediate
属性,开启监听源的首次监听
watch(name, (newData, oldData) => {
console.log(newData, oldData);
}, {
//开启首次监听
immediate: true
})
监听proxy数据
- 当监听值为proxy对象时,
oldValue值
将出现异常
,此时与newValue相同
watch(data, (newData, oldData) => {
//新旧值相同,oldValue无法正确获取
console.log(newData, oldData);
})
监听proxy数据的某个属性
- 需要将监听值写成函数返回形式,vue3无法直接监听对象的某个属性变化
watch(()=>data.sex, (newData, oldData) => {
console.log(newData, oldData);
})
监听proxy数据的某些属性
watch([()=>data.tel,()=>data.sex], (newData, oldData) => {
console.log(newData, oldData);
})
深度监听
- 当监听proxy对象的属性为复杂数据类型时,需要
开启deep深度监听
watch(()=>data.hobby, (newData, oldData) => {
//新旧值相同,oldValue无法正确获取
console.log(newData, oldData);
},{
deep:true
})
注意:
1、
如果定义了reactive的数据,想去使用watch监听数据改变,则无法正确获取旧值,并且deep属性配置无效,自动强制开启了深层次监听。
2、
如果使用 ref 初始化一个对象或者数组类型的数据,会被自动转成reactive的实现方式,生成proxy代理对象。也会变得无法正确取旧值。
3、
用任何方式生成的数据,如果接收的变量是一个proxy代理对象,就都会导致watch这个对象时,watch回调里无法正确获取旧值。
4、
本质是newvalue和oldvalue是指向同一个对象,所以才会产生2者相同的情况,我们可以通过计算属性,将响应式对象转换为ComputedRef的响应式字符串,之后监听这个字符串,将解包后的旧值新值转为对象形式即可
转载自:https://juejin.cn/post/7246283990113452092