Vue2计算属性和侦听器
computed
-
依赖多个变量计算出一个变量,且具有缓存机制,依赖值不变的情况下,会复用计算值。
-
computed
中不能进行异步操作
watch
- 通常监听一个变量的变化,而去做一些事
watvh
中可异步操作
简单记就是:一般情况下computed
的多对一,watch
一对多
computed
获取的计算属性的值为return后面的值
<template>
<div>
<h1>总价为:{{ total }}</h1>
<h1>总价为:{{ total2 }}</h1>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
goods: [
{ id: 1, price: 1, nums: 1 },
{ id: 1, price: 2, nums: 2 },
{ id: 1, price: 3, nums: 3 }
]
}
},
computed: {
// 1.computed格式1
total() {
let res = this.goods.reduce((pre, cur) => {
return pre + cur.price * cur.nums
}, 0)
return res
},
// 2.computed格式2
total2: {
// 使用total2这个属性时,调用get函数
get() {
let res = this.goods.reduce((pre, cur) => {
return pre + cur.price * cur.nums
}, 0)
return res
},
// 修改total2这个属性值时,调用set函数
set(newVal) {
console.log('total2被赋值修改了',newVal);
}
}
}
}
</script>
<style lang="less"></style>
给计算属性传参:以返回函数的形式接收参数。
<template>
<div>
<h1>{{ total(arr1) }}</h1>
<h1>{{ total(arr2) }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
arr1: [1, 2, 3],
arr2: [4, 5, 6]
}
},
computed: {
total(arr) {
return function (arr) {
let res = arr.reduce((pre, cur) => {
return pre + cur
}, 0)
return res
}
}
}
}
</script>
<style lang="less"></style>
watch
<template>
<div>
<h1>{{ name }}</h1>
<button @click="name = 'CCC'">改变姓名</button>
<h1>{{ age }}</h1>
<button @click="age++">改变年龄</button>
</div>
</template>
<script>
export default {
data() {
return {
name: 'cjc',
age: 999
}
},
watch: {
// 方式1
name(newVal, oldVal) {
console.log(newVal, oldVal);
},
// 方式2
age: {
handler(newVal, oldVal) {
console.log(newVal, oldVal);
},
// Vue实例初始化的时候立即调用watch的监听回调函数
immediate: true,
// 深度监听
deep: true
}
}
}
</script>
<style lang="less"></style>
监听对象某个属性
// 监听某个属性
"infos.a": {
handler(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
排除某些属性的监听
mounted() {
Object.keys(this.params)
.filter((_) => !["c", "d"].includes(_)) // 排除对c,d属性的监听
.forEach((_) => {
this.$watch((vm) => vm.params[_], handler, {
deep: true,
});
});
},
data() {
return {
params: {
a: 1,
b: 2,
c: 3,
d: 4
},
};
},
watch: {
params: {
deep: true,
handler() {
this.getList;
},
},
}
Vue3计算属性和侦听器
computed
基本用法
- 多对一
- 有缓存(响应式数据没发生变化时,使用缓存的数据)
- 不能异步代码
<template>
<div>
<h1>总价为:{{ total }}</h1>
<h1>总价为:{{ total2 }}</h1>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
const goods = reactive([
{ id: 1, price: 1, nums: 1 },
{ id: 1, price: 2, nums: 2 },
{ id: 1, price: 3, nums: 3 }
])
// 1.computed格式1 传入回调函数,只支持getter
const total = computed(() => {
return goods.reduce((pre, cur) => {
return pre + cur.price * cur.nums
}, 0)
})
// 2.computed格式2 传入对象,支持getter、setter
const total2 = computed({
get() {
return goods.reduce((pre, cur) => {
return pre + cur.price * cur.nums
}, 0)
},
set(newVal) {
console.log('total2被赋值修改了', newVal);
}
})
total2.value++
</script>
<style scoped></style>
购物车
筛选后的总价:
<template>
<div class="App">
<input type="text" placeholder="输入商品名称" v-model="keyWord" />
<table>
<thead>
<th>物品</th>
<th>数量</th>
<th>单价</th>
<th>价格</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="(item, index) in searchGoods" :key="item.name">
<td>{{ item.name }}</td>
<td>
<button @click="item.num > 1 ? item.num-- : num">-1</button>
{{ item.num }}
<button @click="item.num++">+1</button>
</td>
<td>{{ item.price }}</td>
<td>{{ item.price * item.num }}</td>
<td><button @click="handleDel(index)">删除</button></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">所有物品总价{{ total }}</td>
</tr>
<tr>
<td colspan="5">筛选后的总价{{ total2 }}</td>
</tr>
</tfoot>
</table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue";
let goods = reactive([
{
name: "a",
num: 1,
price: 1,
},
{
name: "b",
num: 2,
price: 2,
},
{
name: "c",
num: 3,
price: 3,
},
]);
// 总价
const total = computed(() => {
return goods.reduce((pre, cur, index) => {
return pre + cur.num * cur.price;
}, 0);
});
const total2 = computed(() => {
return searchGoods.value.reduce((pre, cur, index) => {
return pre + cur.num * cur.price;
}, 0);
});
// 删除
function handleDel(index) {
goods.splice(index, 1);
}
// 搜索
const keyWord = ref<string>("");
const searchGoods = computed(() => {
return goods.filter((item, index) => {
return item.name.includes(keyWord.value);
});
});
</script>
<style scoped>
th,
td {
border: 1px solid #ccc;
}
td {
text-align: center;
padding: 10px;
}
</style>
给计算属性传参
给计算属性传参:以返回函数的形式接收参数。
<template>
<div>
<h1>{{ total(arr1) }}</h1>
<h1>{{ total(arr2) }}</h1>
<!-- <h1>总价为:{{ total2 }}</h1> -->
</div>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
const arr1 = reactive([1, 2, 3])
const arr2 = reactive([1, 1, 1])
// 给计算属性传参:以返回函数的形式接收参数。
const total = computed((arr) => {
return function (arr) {
return arr.reduce((pre, cur) => {
return pre + cur
}, 0)
}
})
</script>
<style scoped></style>
watch
基本使用
- 一对多
- 没有有缓存
- 能异步代码
<template>
<div class="App">
<!-- <input type="text" v-model="objRef.a.b.c" /> -->
<div>姓名:<input type="text" v-model="name" /></div>
<div>年龄:<input type="text" v-model="age" /></div>
<div>objRef:<input type="text" v-model="objRef.a.b.c" /></div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
// 1.监听多个数据源
const name = ref("cjc");
const age = ref(100);
watch(
[name, age],
(newArr, oldArr) => {
console.log("newArr", newArr);
console.log("oldArr", oldArr);
},
{
deep: true,
}
);
// 2.监听对象的某一属性
const objRef = ref({
a: {
b: {
c: "c",
},
},
});
watch(
() => objRef.value.a.b.c,
(val, oldValue) => {
console.log(val, oldValue);
},
{
deep: true,
}
);
</script>
watchEffect
基本用法
- 初始时自动调用一次回调函数
- 回调函数中用到几个监听几个,watchEffect 自动收集响应式数据的依赖
- 当依赖发生变化时,回调函数再次执行,执行过程中收集依赖
<template>
<div class="App">
{{ info.arr }}
<button @click="info.arr.push('c')">添加arr</button>
<button @click="info.name = 'cjc'">修改name</button>
<button @click="stopWatch()">暂停监听</button>
</div>
</template>
<script setup lang="ts">
import { ref, watchEffect } from "vue";
const info = ref({
name: "CCC",
age: 999,
arr: ["a", "b"],
});
// watchEffect返回暂停监听器函数
const stopWatch = watchEffect((onCleanup) => {
// 修改基本类型的值
console.log(info.value.name);
// 修改引用类型的值,不触发监听
console.log(info.value.arr);
});
</script>
清除副作用
就是在触发监听之前会调用一个函数可以处理你的逻辑例如防抖
const stopWatch = watchEffect(
(onCleanup) => {
console.log(info.value.name);
console.log(info.value.arr);
onCleanup(() => {
console.log("触发监听后最先执行的逻辑");
});
},
{
flush: "sync",
}
);
副作用刷新时机 flush 一般使用post
- pre 组件更新之前
- sync 强制同步执行
- post 组件更新之后