Vue app 可以有 4 个配置选项:
data
methods
computed
watch
即:
const app = Vue.createApp({
data() {
return { ... };
},
computed: {
// ...
},
methods: {
// ...
},
watch: {
// ...
}
});
app.mount("#root");
如果不考虑性能,计算属性 computed
可以全部放到 methods
里。
使用计算属性的目的只是为了改善性能。
原因是,HTML 页面上发生任何改变,v-bind
, v-html
, {{ }}
中的任何方法,即任意非事件绑定的方法都将被重新执行,影响 performance,因为 Vue 不清楚 methods
里方法的依赖关系。
以下是一段简单的代码,点击两个按钮,分别对一个数字加或减,也可以输入name
和 lastname
, 二者相加输出 fullname。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Basicstitle>
<link
href="https://fonts.googleapis.com/css2?family=Jost:wght@400;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css" />
<script src="https://unpkg.com/vue@next" defer>script>
<script src="app.js" defer>script>
head>
<body>
<header>
<h1>Vue Eventsh1>
header>
<section id="events">
<h2>Events in Actionh2>
<button v-on:click="add(5)">Addbutton>
<button v-on:click="reduce(5)">Reducebutton>
<p>Result: {{ counter }}p>
<input type="text" v-model="name" />
<input type="text" v-model="lastName" />
<p>Your name: {{outputFullname()}}p>
section>
body>
html>
// app.js
const app = Vue.createApp({
data() {
return {
counter: 0,
name: "",
lastName: "",
};
},
methods: {
outputFullname() {
console.log("outputFullname executed!");
if (this.name === "") {
return "";
}
return this.name + " " + this.lastName;
},
add(x) {
this.counter += x;
},
reduce(x) {
this.counter -= x;
},
setName(e, lastName) {
this.name = e.target.value;
},
},
});
app.mount("#events");
输出 fullname 是通过调用 methods
里的 outputFullname()
实现的,表面上看代码 ok,没有任何问题。
但是如果打开console,点击 add 或者 reduce 按钮加减数字,就会发现 outputFullname()
也在执行,虽然数字和姓名两个部分二者是完全独立的,没有任何关联。页面上的发生任何变化,此方法都将被重新执行一遍,这就是问题所在。因为 Vue 无法知道这个method 即 outputFullname()
究竟在干什么。
显然这是一个需要优化的地方,需要使得数字在进行加减,即点击 add 或者 reduce 按钮时,outputFullname()
不会执行。
优化的方法就是使用计算属性,将 outputFullname()
改用 computed
即计算属性实现,也就是将 outputFullname()
的逻辑放到 computed
里。计算属性实质上类似于方法,但是有一个重要的区别:Vue 明白它们的依赖,仅仅当某个依赖变化时才会重新执行。
HTML 修改:
<p>Your name: {{fullname}}p>
app.js 增加 computed
属性,outputFullname()
不再使用。
data() {
// ....
},
computed: {
fullname() {
console.log("fullname in computed executed!");
if (this.name === "") {
return "";
}
return this.name + " " + this.lastName;
},
},
methods: {
// ...
}
可以像使用 data properties 一样使用 computed properties, computed properties 里的方法的命名类似于数据属性,所以 computed
里使用的方法名称是 fullname
, 而非 outputFullname
, 同样,计算属性被当成数据属性使用,因此计算属性不能调用,下面的 fullname
后不能加括号:
<p>Your name: {{fullname}}p>
改为使用计算属性,当点击 reduce 或者 add,不再出现之前的方法无条件重复执行问题:
模板里不会直接使用 watch
,使用 watch
可以监视数据属性或者计算属性的变化,从而执行某些操作对数据的改变作出反应。watch
里的方法名重复使用任意 data
属性名或者 computed
属性名,watch
里的方法由于返回值不会被用到,因此没有 return
语句。
watch: {
any_name_of_data_or_computed_properties (newValue, oldValue) { ... }
}
watch
可以接受两个参数,newValue
是最新值,oldValue
是上一次的值,如果代码需要可以写两个,newValue
,oldValue
也可以改成别的名称。
下面的代码,任意点击 add, 或者 reduce 按钮若干次,如果 counter
大于 50,Vue 将在两秒之后自动重置 counter
为 0
:
const app = Vue.createApp({
data() {
return {
counter: 0,
name: "",
lastName: "",
};
},
computed: {
},
watch: {
counter(v) {
if (v > 50) {
const that = this;
setTimeout( ()=> {
that.counter = 0;
}, 2000);
}
},
},
methods: {
// ...
},
});
app.mount("#events");