Appearance
30.computed 和 watch 区别
Vue2 中有三种 watcher (渲染 watcher 、计算属性 watcher、 用户 watcher)
Vue3 中有三种 effect (渲染 effect 、计算属性 effect、 用户 effect)
1.1 computed
- 计算属性仅当用户取值时才会执行对应的方法。
- computed 属性是具备缓存的,依赖的值不发生变化,对其取值时计算属性方法不会重新执行。
- 计算属性可以简化模板中复杂表达式。
- 计算属性中不支持异步逻辑。
- computed 属性是可以再模板中使用的。
1.2 watch
watch 则是监控值的变化,当值发生变化时调用对应的回调函数。经常用于监控某个值的变化,进行一些操作。(异步要注意竞态问题。)
vue
<template>
<div>
<input v-model="value" />
{{ result }}
</div>
</template>
<script>
export default {
name: "App",
components: {},
data() {
return {
result: "",
timer: 3000,
};
},
methods: {
async getData(newVal) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(newVal);
}, (this.timer -= 1000));
});
},
},
mounted() {
let arr = [];
this.$watch("value", async (newVal, oldValue) => {
let clear = false;
while (arr.length > 0) {
arr.shift()();
}
arr.push(() => {
clear = true; // 利用闭包实现清理操作
});
let result = await this.getData(newVal);
if (!clear) this.result = result;
});
},
};
</script>
<template>
<div>
<input v-model="value" />
{{ result }}
</div>
</template>
<script>
export default {
name: "App",
components: {},
data() {
return {
result: "",
timer: 3000,
};
},
methods: {
async getData(newVal) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(newVal);
}, (this.timer -= 1000));
});
},
},
mounted() {
let arr = [];
this.$watch("value", async (newVal, oldValue) => {
let clear = false;
while (arr.length > 0) {
arr.shift()();
}
arr.push(() => {
clear = true; // 利用闭包实现清理操作
});
let result = await this.getData(newVal);
if (!clear) this.result = result;
});
},
};
</script>
vue3 提供了 onCleanup 函数,让用户更加方便使用也解决了清理问题。
js
watch(
() => this.value,
async (newVal, oldValue, onCleanup) => {
let clear = false;
onCleanup(() => {
clear = true;
});
let result = await this.getData(newVal);
if (!clear) this.result = result as string;
}
);
watch(
() => this.value,
async (newVal, oldValue, onCleanup) => {
let clear = false;
onCleanup(() => {
clear = true;
});
let result = await this.getData(newVal);
if (!clear) this.result = result as string;
}
);