computed, watch, update 的使用和区别
约 1337 字大约 4 分钟
2025-08-01
watch
watch
监听 data
中的数值,需要先在 watch:{ }
中绑定要监听的值,监听的数值只要变化,就执行 watch
- 默认情况下,变量被初始化的时候,
watc
h 不会立即执行,如果想要立即执行,使用watch
的immediate
属性。 - 如果
watch
监听的是一个对象,则对象中的属性值变化,watch
无法监听到。如果想要监听,使用watch
的deep
属性。
updated
updated 监听 template 中绑定的值,要监听的数值只要变化,就执行 updated
- 不用额外添加监听方法,只要在 template 中绑定,update 自动监听
计算属性 VS 侦听器
- computed 属性侧重监听多个数据的变化,并返回一个计算出的新值
- watch 属性侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值
计算属性 VS 普通方法
- 计算属性中不应该改变 data 中的变量值(会报错:Unexpected side effect in "plus" computed property)
- methods 中的方法可以改变 data 中的变量值
- computer 有缓存,数字不变时只执行 1 次,性能高
- methods 中的函数无缓存,数字不变时也执行 3 次,性能不如 computer
代码
computed.vue
<template>
<div>
<h2>{{ msg }}</h2>
<input v-model.number="count" />
<p></p>
<!-- computer 有缓存,数字不变时只执行1次,性能高 -->
<div class="box">
<h4>使用computer 属性</h4>
<p>computer:{{ count }} ✖ 2 = {{ plus }}</p>
<p>computer:{{ count }} ✖ 2 = {{ plus }}</p>
<p>computer:{{ count }} ✖ 2 = {{ plus }}</p>
</div>
<!-- methods中的函数无缓存,数字不变时也执行3次,性能不如computer -->
<div class="box">
<h4>使用 methods function</h4>
<p>methods:{{ count }} ✖ 2 = {{ plusM() }}</p>
<p>methods:{{ count }} ✖ 2 = {{ plusM() }}</p>
<p>methods:{{ count }} ✖ 2 = {{ plusM() }}</p>
</div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
count: 1,
};
},
/*
计算属性 必须定义在 computer 节点中
计算属性必须是一个function,必须有返回值
计算属性使用时必须当作普通属性来使用,不能加()
计算属性中不应该改变 data 中的变量值(会报错:Unexpected side effect in "plus" computed property)
*/
computed: {
/*
从 computed 读取三遍,只计算一次,后两次从缓存中读取,性能较高
如果记住状态了,比如淘宝购物车,再次渲染页面的时候也直接从computer读取缓存,
methods则要重新计算,尤其是数据量大的时候,computed可以节省大量性能
如果你不希望有缓存,请用 method 来替代
computed VS watch: https://segmentfault.com/a/1190000021029299?utm_source=tag-newest
*/
plus() {
console.log("计算属性执行了");
return this.count * 2;
},
},
methods: {
// 调用三遍,执行三遍,计算三遍,性能较低
plusM() {
console.log("方法执行了");
return this.count * 2;
},
},
};
</script>
<style scoped>
.box {
display: inline-block;
border: 1px solid gray;
margin: 10px;
padding: 20px;
}
</style>
watch.vue
<template>
<div>
<h2>{{ msg }}</h2>
<!-- v-model 后有三个属性可选,lazy | trim | number lazy是input失去焦点后绑定数据;trim是去除空格;number是限定数字 -->
<input type="text" v-model.number="username" />
</div>
</template>
<script>
import axios from "axios";
export default {
name: "WatchAttribute",
props: {
msg: String,
},
data() {
return {
username: "",
};
},
computed: {
/*
计算属性 VS 侦听器
侧重的应用场景不同:
1. computed 属性侧重监听多个数据的变化,并返回一个计算出的新值;
2. watch 属性侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值。
*/
},
/*
watch 监听 data 中的数值,要监听的数值只要变化,就执行watch
1. 默认情况下,变量被初始化的时候,watch不会立即执行,如果想要立即执行,使用 watch 的immediate 属性。
2. 如果watch监听的是一个对象,则对象中的属性值变化,watch无法监听到。如果想要监听,使用 watch 的 deep 属性。
*/
watch: {
/* watch 基本使用 */
// username(newValue, oldValue){
// console.log('new:',newValue);
// console.log('old:',oldValue);
// }
/*
使用 axios 检查用户名是否可用
1. 安装 axios : npm i axios -S
2. axios 返回一个 promise 对象,可以用 await 简化成真正的数据对象
3. 有 await ,函数名前面必须加 async 修饰
*/
async username(newValue) {
console.log("newvalue:", newValue);
// axios 返回一个 promise 对象,可以用 await 解构成真正的数据对象
// const res = await axios.get("https://www.escook.cn/api/finduser/" + newValue);
// 返回的数据对象中只有 data 属性有意义,我们可以用 {data} 来结构赋值,用{data :res} 给data部分重命名
if (newValue) {
const { data: res } = await axios.get(
"https://www.escook.cn/api/finduser/" + newValue
);
console.log("res:", res);
}
},
},
methods: {},
updated() {
/*
template中绑定的值变化了就会触发 updated
*/
console.log("updated");
},
};
</script>
<style scoped></style>
watch 和 updte 对比
<template>
<div>
<h2>{{ msg }}</h2>
<input type="text" v-model.number="count" />
<span>count:{{ count }}</span>
<input type="text" v-model.trim="user" />
<span>user:{{ user }}</span>
</div>
</template>
<script>
export default {
name: "LifeCycle",
components: {},
props: {
msg: String,
},
data() {
return {
count: 0,
user: "",
};
},
watch: {
/*
watch 监听 data 中的数值,要监听的数值只要变化,就执行watch
在本例中:
1. 监听了 count ,所以count发生变化会执行 watch
2. 没有监听 user,所以 user 发生变化也不会执行 watch
*/
count(newvalue) {
console.log("watch:", newvalue);
},
},
updated() {
/*
template中绑定的值变化了就会触发 updated
在本例中:
1. count 改变会触发 update
2. user 改变也会触发 update
*/
console.log("update");
},
activated() {},
beforeUnmount() {},
unmounted() {},
};
</script>
<style scoped></style>