学习目录:
- Vue.js 简介
- Vue.js 实例与数据绑定
- Vue.js 计算属性和侦听器
- Vue.js 条件渲染和列表渲染
- Vue.js 事件处理
- Vue.js 表单输入绑定
- Vue.js 组件基础
- Vue.js 组件通信
- Vue.js 插槽
- Vue.js 动态组件和异步组件
- Vue.js 自定义指令
- Vue.js 过渡和动画
- Vue.js 混入
- Vue.js 自定义事件和 v-model
- Vue.js 渲染函数和 JSX
- Vue.js 插件
- Vue.js 单文件组件
- Vue.js Webpack 配置和打包优化
- Vue.js Vue Router
- Vue.js Vuex
- Vue.js 服务端渲染
- Vue.js 代码测试和调试
- Vue.js 生态系统
- Vue.js 最佳实践和性能优化
- Vue.js 应用部署和上线
Vue.js 是一种流行的前端 JavaScript 框架,它提供了许多有用的功能来简化开发人员的工作。在 Vue.js 中,计算属性和侦听器是两个非常有用的功能,可以帮助我们更轻松地处理数据和响应用户输入。在本文中,我们将深入研究这两个功能以及如何在 Vue.js 中使用它们。
计算属性
计算属性是一种可以根据其他属性计算并返回值的属性。这个过程是自动完成的,当计算属性所依赖的属性发生变化时,计算属性会被重新计算。Vue.js 的计算属性可以使我们更轻松地处理一些复杂的逻辑,例如格式化数据或者排序数组。
基本用法
下面是一个简单的计算属性示例,该计算属性返回数组 items
中的元素数量:
<template>
<div>
<p>数组中有 {{ itemCount }} 个元素</p>
</div>
</template>
<script>
export default {
data() {
return {
items: ["apple", "orange", "banana"]
};
},
computed: {
itemCount() {
return this.items.length;
}
}
};
</script>
在上面的代码中,我们定义了一个数组 items
,并定义了一个计算属性 itemCount
,该计算属性返回数组 items
的长度。在模板中,我们使用插值语法 {{ itemCount }}
来显示计算属性的值。
当 items
数组发生变化时,计算属性 itemCount
会自动重新计算,并更新模板中的值。这意味着我们不需要手动更新 itemCount
属性,Vue.js 会自动处理它。
计算属性 vs. 方法
我们可以将上面的计算属性 itemCount
转换为一个方法。下面是一个示例:
<template>
<div>
<p>数组中有 {{ itemCount() }} 个元素</p>
</div>
</template>
<script>
export default {
data() {
return {
items: ["apple", "orange", "banana"]
};
},
methods: {
itemCount() {
return this.items.length;
}
}
};
</script>
在上面的代码中,我们将计算属性 itemCount
转换为了一个方法 itemCount()
。在模板中,我们使用 {{ itemCount() }}
来调用该方法,并显示它的返回值。
虽然这段代码可以工作,但是它并不如使用计算属性那么高效。因为计算属性是一个缓存值,只有在它所依赖的属性发生变化时才会重新计算。而当我们使用方法时,每次模板重新渲染时都会调用方法。因此,在处理复杂逻辑的情况下,计算属性通常比方法更适合。
计算属性的 Setter
在某些情况下,我们可能需要在计算属性中进行双向绑定,也就是说,当计算属性的值发生变化时,我们希望更新其依赖的属性。为了实现这一点,我们可以为计算属性定义一个 setter 方法。
下面是一个示例,该示例将计算属性 fullName
分解为 firstName
和 lastName
属性,并且可以通过修改 fullName
属性来更新 firstName
和 lastName
属性:
<template>
<div>
<input v-model="fullName" placeholder="Full Name" />
<p>First Name: {{ firstName }}</p>
<p>Last Name: {{ lastName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: "",
lastName: ""
};
},
computed: {
fullName: {
get() {
return this.firstName + " " + this.lastName;
},
set(value) {
const names = value.split(" ");
this.firstName = names[0];
this.lastName = names[1];
}
}
}
};
</script>
在上面的代码中,我们定义了一个计算属性 fullName
,该计算属性通过 firstName
和 lastName
属性计算而来。在模板中,我们使用 v-model
指令将 fullName
属性绑定到一个输入框上。当输入框中的值发生变化时,Vue.js 会调用 fullName
的 setter 方法,该方法将输入框中的值分解为 firstName
和 lastName
属性,并将它们分别存储在组件的 data 中。
计算属性的缓存
Vue.js 会缓存计算属性的值,只有在计算属性的依赖发生变化时才会重新计算。这意味着当计算属性的依赖没有发生变化时,Vue.js 可以直接从缓存中读取计算属性的值,而不需要重新计算。
下面是一个示例,该示例演示了计算属性的缓存机制:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
data() {
return {
items: ["apple", "orange", "banana"],
counter: 0
};
},
computed: {
count() {
console.log("Computing count");
return this.items.length + this.counter;
}
},
methods: {
increment() {
this.counter++;
}
}
};
</script>
在上面的代码中,我们定义了一个计算属性 count
,该计算属性返回数组 items
的长度加上 counter
属性的值。在模板中,我们显示计算属性的值,并定义了一个按钮,每次点击该按钮时,都会将 counter
属性增加 1。
当我们首次渲染组件时,计算属性会被计算一次,并将结果缓存起来。当我们点击按钮时,只有 counter
属性发生了变化,因此 Vue.js 只会重新计算 count
计算属性,而不会重新计算 items
数组的长度。这意味着当我们点击按钮时,控制台上只会输出一次计算属性的结果,而不会输出两次。
计算属性的 Getter 和 Setter
计算属性既可以有 getter,也可以有 setter。当我们为计算属性定义 setter 时,我们可以在计算属性发生变化时执行一些操作。下面是一个示例,该示例演示了如何为计算属性定义 getter 和 setter:
<template>
<div>
<p>{{ fullName }}</p>
<input v-model="firstName" placeholder="First Name" />
<input v-model="lastName" placeholder="Last Name" />
</div>
</template>
<script>
export default {
data() {
return {
firstName: "",
lastName: ""
};
},
computed: {
fullName: {
get() {
return this.firstName + " " + this.lastName;
},
set(value) {
const names = value.split(" ");
this.firstName = names[0];
this.lastName = names[1];
}
}
}
};
</script>
在上面的代码中,我们定义了一个计算属性 fullName
,该计算属性包含了 getter 和 setter 方法。在模板中,我们使用 v-model
指令将 firstName
和 lastName
属性绑定到两个输入框上。当输入框中的值发生变化时,Vue.js 会调用计算属性的 setter 方法,并将输入框中的值合并为一个完整的名字。
侦听器
侦听器是一种可以侦听属性的变化并执行操作的功能。当我们需要在属性发生变化时执行异步操作或一些复杂的操作时,侦听器非常有用。
非常抱歉,似乎我的前一个答案被截断了。下面是继续讲解侦听器的内容。
基本用法
下面是一个简单的侦听器示例,该侦听器侦听数组 items
的变化,并在数组发生变化时更新 itemCount
计数器:
<template>
<div>
<p>数组中有 {{ itemCount }} 个元素</p>
<button @click="addItem">添加元素</button>
</div>
</template>
<script>
export default {
data() {
return {
items: ["apple", "orange", "banana"],
itemCount: 0
};
},
watch: {
items() {
this.itemCount = this.items.length;
}
},
methods: {
addItem() {
this.items.push("pear");
}
}
};
</script>
在上面的代码中,我们定义了一个数组 items
和一个计数器 itemCount
。我们还定义了一个侦听器,该侦听器侦听数组 items
的变化,并在数组发生变化时更新计数器。
在模板中,我们显示计数器的值,并定义了一个按钮,点击该按钮时,会向数组中添加一个新元素。当数组发生变化时,Vue.js 会调用侦听器,并将计数器更新为数组的新长度。
深度侦听
在默认情况下,Vue.js 的侦听器只会侦听对象或数组本身的变化,而不会侦听它们的属性或元素的变化。这意味着如果我们修改了对象或数组中的某个属性或元素,侦听器不会自动触发。如果我们需要侦听对象或数组中属性或元素的变化,我们可以使用深度侦听。
下面是一个示例,该示例演示了如何使用深度侦听来侦听对象属性的变化:
<template>
<div>
<p>{{ user.name }}</p>
<input v-model="user.name" placeholder="Name" />
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: "John",
age: 30
}
};
},
watch: {
user: {
handler() {
console.log("User changed");
},
deep: true
}
}
};
</script>
在上面的代码中,我们定义了一个对象 user
,该对象包含 name
和 age
两个属性。在模板中,我们显示 user.name
属性,并使用 v-model
指令将输入框绑定到 user.name
属性上。
我们还定义了一个侦听器,该侦听器侦听 user
对象的变化,并在对象发生变化时输出一条消息。由于我们将 deep
设置为 true
,因此侦听器会侦听 user
对象及其所有属性的变化,包括 user.name
属性。
侦听器的回调
侦听器可以接收两个参数:新值和旧值。这意味着我们可以在侦听器中比较新值和旧值,并执行一些操作。
下面是一个示例,该示例演示了如何在侦听器中比较新值和旧值:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
};
},
watch: {
count(newValue, oldValue) {
console.log(`Count changed from ${oldValue} to ${newValue}`);
}
},
methods: {
increment() {
this.count++;
}
}
};
</script>
在上面的代码中,我们定义了一个计数器 count
,并定义了一个侦听器,该侦听器侦听 count
的变化,并在变化发生时输出一条消息,该消息显示计数器从旧值变为新值的值。我们还定义了一个方法 increment()
,该方法将计数器的值增加1。
当我们单击“Increment”按钮时,计数器的值将增加1。由于我们定义了一个侦听器,因此当计数器的值发生变化时,侦听器会被调用,并将新值和旧值作为参数传递给该侦听器。在上面的示例中,我们将新值和旧值输出到控制台中,以便我们可以比较它们。