vue 计算属性和侦听器
完整代码示例:demo-计算属性-方法-侦听器
计算属性
什么是计算属性?
本质还是属性,但是它的属性值必须是函数
为什么需要计算属性和侦听器?
计算属性computed 主要解决模板template 中放入太多运算逻辑问题。而侦听器watch 能实现计算属性computed 所能实现的所有功能。
那么二者的区别在于哪?
- 计算属性
computed 是监听依赖的值是否变化,如依赖的值有变化会触发回调,否则直接使用缓存的值。 - 当需要在数据变化时执行 异步 或 开销较大 的操作时,使用侦听器
watch 是最好的选择。
我们来看个template 模板内的表达式,看起来非常便利,但是设计模板template 使用JavaScript 表达式的初衷是用于简单运算的。 在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
为了解决难以维护的问题,我们可以用计算属性computed 来优化
对于任何复杂逻辑,你都应当使用计算属性。
如reversedMessage :
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
data: {
message: 'Hello'
},
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
上面的方法还可以使用方法methods 实现。
使用方法实现数据填充:
<p>Reversed message: "{{ reversedMessage() }}"</p>
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
那么计算属性computed 和方法methods 的主要区别是计算属性computed 是基于数据的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
计算属性computed 默认只提供了get 方法,如果我们需要可以新增set 方法,代码如下:
<p>Computed Setter reversed message: "{{ fullName }}"</p>
<button @click="onClick">更新用户名</button>
data() {
return {
firstName: "张",
lastName: "三",
};
},
methods: {
onClick() {
this.fullName = "John Doe";
},
},
computed: {
reversedMessage: function () {
return this.message.split("").reverse().join("");
},
fullName: {
get: function () {
return this.firstName + " " + this.lastName;
},
set: function (newValue) {
this.firstName = "李";
this.lastName = "四";
},
},
},
侦听器
上面的computed 实现字符串反转也可以使用侦听器watch 实现,
使用watch 监听
<p>Watch Reversed message: "{{ watchReversedMessage }}"</p>
data() {
return {
message: "Hello",
watchReversedMessage: "",
};
},
watch: {
message: {
handler(newVal, oldVal) {
this.watchReversedMessage = newVal.split("").reverse().join("");
},
},
},
写完上面的侦听器watch 代码,我们可以看到hello 并没有第一时间反转。只有在你改变message 的值之后才会执行侦听器watch 里面的代码 那么有没有什么办法可以立即就执行侦听器watch 的代码呢?
有的,通过设置immediate:true ,即可实现立即渲染,也就是刚进入页面就执行watch 里面的代码。 代码如下:
<p>Watch Reversed message: "{{ watchReversedMessage }}"</p>
data() {
return {
message: "Hello",
watchReversedMessage: "",
};
},
watch: {
message: {
handler(newVal, oldVal) {
this.watchReversedMessage = newVal.split("").reverse().join("");
},
immediate: true,
},
},
有时候我们想监听对象属性的改变。比如我们想在输入框中的值修改后能被监听到,根据上面的思路,我们会写出下面的代码
<p>Watch Deep Reversed message: "{{ obj.message }}"</p>
<input v-model="obj.message" placeholder="输入值看deep监听是否观察到" />
data() {
return {
obj: {
message: "World",
},
};
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log("有改变:", newVal);
},
immediate: true,
},
},
虽然v-model 中的值会更新到p 标签中显示,但是我们在watch 里面监听不到obj 对象的变化,也就是没看到console.log("有改变:", newVal); 输出。
这时候不要慌,我们看下watch api 发现了deep 属性,通过设置deep:true 即可解决。
<p>Watch Deep Reversed message: "{{ obj.message }}"</p>
<input v-model="obj.message" placeholder="输入值看deep监听是否观察到" />
data() {
return {
obj: {
message: "World",
},
};
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log("有改变:", newVal);
},
immediate: true,
deep: true
},
},
完整代码示例:demo-计算属性-方法-侦听器
– end –
|