概述
Vue watchers programmatically observe component data and run whenever a particular property changes. Watched data can contain two arguments: oldVal and newVal. This can help you when writing expressions to compare data before writing or binding new values. Watchers can observe objects as well as other types, such as string, number, and array types.
Vue 观察器以编程方式观察组件数据,并在特定属性发生变化时运行。观察数据可包含两个参数:oldVal 和 newVal。这有助于您在编写表达式时,在写入或绑定新值之前比较数据。观察者可以观察对象以及其他类型,如字符串、数字和数组类型。
To clean up your watcher code, you can assign a handler argument to a defined component’s method, which is considered best practice for large projects.
要清理观察者代码,可以为已定义组件的方法指定一个处理程序参数,这被认为是大型项目的最佳做法。
Watchers complement the usage of computed data since they passively observe values and cannot be used as normal Vue data variables, while computed data must always return a value and can be looked up. Remember not to use arrow functions if you need the Vue context of this.
观察者是对计算数据使用的补充,因为它们被动地观察值,不能作为普通的 Vue 数据变量使用,而计算数据必须始终返回值,并且可以查询。如果需要 Vue 上下文,切记不要使用箭头函数。
The following example demonstrates the immediate and deep optional keys; if any key inside the myDataProperty object were to change, it would trigger a console log:
下面的示例演示了即时和深度可选键;如果 myDataProperty 对象中的任何键发生变化,都会触发控制台日志:
<script>
export default {data() {return {}},watch: {myDataProperty: {handler: function(newVal, oldVal) {console.log('myDataProperty changed:', newVal, oldVal)},immediate: true,deep: true},}
}
</script>
练习:监听器的基本使用
In this exercise, you will use watcher arguments to watch data properties for changes, then use this watcher to set variables via a method.
在本练习中,您将使用观察者参数来监视数据属性的变化,然后使用该观察者通过方法设置变量。
Let’s create a new Vue component called Exercise2-03 by adding the Exercise2-03.vue file to the ./src/components/ folder.
让我们在 ./src/components/ 文件夹中添加 Exercise2-03.vue 文件,创建一个名为 Exercise2-03 的新 Vue 组件。
修改App.vue,引入该组件并进行渲染:
<script setup>
import Exercise from "./components/Exercise2-03.vue";
</script>
<template><Exercise/>
</template>
Open Exercise2-03.vue and let’s create the code block structure for the Vue component, as follows:
打开 Exercise2-03.vue,创建 Vue 组件的代码块结构如下:
<template>
</template>
<script>
export default {
}
</script>
Set up the document by adding a discount and an oldDiscount data:
通过添加折扣和旧折扣数据来设置文档:
<template><div class="container"><h1>Shop Watcher</h1><div>Black Friday sale<strike>Was {{ oldDiscount }}%</strike><strong> Now {{ discount }}% OFF</strong></div></div>
</template>
<script>
export default {data() {return {oldDiscount: 0,discount: 5,}},
}
</script>
We want to listen to the changes in the discount property. This can be achieved by adding it to the watch object and manually updating the oldDiscount value to oldValue received as follows:
我们希望监听折扣属性的变化。为此,我们可以将其添加到观察对象中,并将收到的 oldDiscount 值手动更新为 oldValue,如下所示:
<script>
export default {data() {return {oldDiscount: 0,discount: 5,}},watch: {discount(newValue, oldValue) {this.oldDiscount = oldValue},},
}
</script>
Now let’s add a component method called updateDiscount. Inside the method, set the oldDiscount data prop to this.discount + 5:
现在,让我们添加一个名为 updateDiscount 的组件方法。在该方法中,将 oldDiscount 数据道具设置为 this.discount + 5:
<script>
export default {data() {return {oldDiscount: 0,discount: 5,}},methods: {updateDiscount() {this.discount = this.discount + 5},},watch: {discount(newValue, oldValue) {this.oldDiscount = oldValue},},
}
</script>
Then bind this method to button using the @click directive to trigger this method whenever the user clicks on the button and respectively trigger the watcher:
然后使用 @click 指令将此方法绑定到按钮上,以便在用户点击按钮时触发此方法,并分别触发观察者:
<template><div class="container"><h1>Shop Watcher</h1><div>Black Friday sale<strike>Was {{ oldDiscount }}%</strike><strong> Now {{ discount }}% OFF</strong></div><button @click="updateDiscount">Increase Discount!</button></div>
</template>
Add some CSS stylings to make our component look pretty:
添加一些 CSS 样式,让我们的组件看起来更漂亮:
<template><div class="container"><h1>Shop Watcher</h1><div>Black Friday sale<strike>Was {{ oldDiscount }}%</strike><strong> Now {{ discount }}% OFF</strong></div><button @click="updateDiscount">Increase Discount!</button></div>
</template>
<script>
export default {data() {return {oldDiscount: 0,discount: 5,}},methods: {updateDiscount() {this.discount = this.discount + 5},},watch: {discount(newValue, oldValue) {this.oldDiscount = oldValue},},
}
</script><style scoped>
.container {margin: 0 auto;padding: 30px;max-width: 600px;font-family: 'Avenir', Helvetica, Arial, sans-serif;
}button {display: inline-block;background: rgb(235, 50, 50);border-radius: 10px;font-size: 14px;color: white;padding: 10px 20px;text-decoration: none;
}
</style>
In this exercise, we explored how we can use watchers to observe and dynamically manipulate data when it is changed by triggering other methods in the Vue component.
在本练习中,我们探索了如何使用观察者来观察数据,并在数据发生变化时通过触发 Vue 组件中的其他方法来动态处理数据。
Next, we will learn how to actively watch a specific nested property within a data object through deep watching.
接下来,我们将学习如何通过深度观察来主动观察数据对象中的特定嵌套属性。
监听嵌套的属性
When using Vue.js to watch a data property, you can observe changes belonging to nested keys of an object, rather than observing the changes to the object itself.
使用 Vue.js 观察数据属性时,你可以观察到属于对象嵌套键的变化,而不是观察对象本身的变化。
This is done by setting the optional deep property to true:
这可以通过将可选的 deep 属性设置为 true 来实现:
<script>
export default {data() {return {organization: {name: 'ABC',employees: ['Jack', 'Jill']}}},watch: {organization: {handler(v) {this.sendIntercomData()},deep: true,immediate: true,},},
}
</script>
This code example demonstrates how we watch all available keys inside the organization data object for changes. If the name property inside organization changes, the organization watcher will trigger.
本代码示例演示了如何观察组织数据对象中所有可用键的变化。如果组织内部的 name 属性发生变化,组织观察器就会触发。
If you do not need to observe every key inside an object, it is more performant to assign a watcher to a specific key by specifying it following the syntax <object>.<key>
string. For example, you may allow a user to edit their company name and trigger an API call when that specific key’s value has been modified.
如果不需要观察对象中的每个键,那么按照 <object>.<key>
字符串的语法为特定键指定观察者会更有效。例如,您可以允许用户编辑自己的公司名称,并在特定键值被修改时触发 API 调用。
In the following example, the watcher is explicitly observing the name key of the organization object:
在下面的示例中,观察者明确观察组织对象的名称键:
<script>
export default {data() {return {organization: {name: 'ABC',employees: ['Jack', 'Jill']}}},watch: {'organization.name': {handler: function(v) {this.sendIntercomData()},immediate: true,},},
}
</script>
练习:监听对象的嵌套属性
In this exercise, you will use watchers to observe keys within an object, which will update when a user triggers a method within the UI.
在本练习中,您将使用观察者来观察对象中的键,当用户触发用户界面中的方法时,这些键就会更新。
Let’s create a new Vue component called Exercise2-04 by adding the Exercise2-04.vue file to the ./src/components/ folder:
让我们在 ./src/components/ 文件夹中添加 Exercise2-04.vue 文件,创建一个名为 Exercise2-04 的新 Vue 组件:
在App.vue中,引入该组件并渲染:
<script setup>
import Exercise from "./components/Exercise2-04.vue";
</script>
<template><Exercise/>
</template>
In Exercise2-04.vue, let’s start by defining a product object that contains price and label, and a discount key. Output these values into the template:
在 Exercise2-04.vue 中,我们先定义一个包含价格、标签和折扣键的产品对象。将这些值输出到模板中:
<template><div class="container"><h1>Deep Watcher</h1><div><h4>{{ product.label }}</h4><h5>${{ product.price }} (${{ discount }}Off)</h5></div></div>
</template>
<script>
export default {data() {return {discount: 0,product: {price: 25,label: 'Blue juice',},}},
}
</script>
Add CSS styling to our component:
为我们的组件添加 CSS 样式:
<style scoped>
.container {margin: 0 auto;padding: 30px;max-width: 600px;font-family: 'Avenir', Helvetica, sans-serif;
}button {display: inline-block;background: rgb(235, 50, 50);border-radius: 10px;font-size: 14px;color: white;padding: 10px 20px;text-decoration: none;
}
</style>
Now let’s set up a button that will modify the price of the product. We achieve this by adding a button element with a click event bound to an updatePrice method that decrements the value of the price:
现在,让我们设置一个按钮来修改产品的价格。为此,我们添加了一个按钮元素,其点击事件绑定到一个 updatePrice 方法上,该方法会递减价格值:
<template><div class="container"><h1>Deep Watcher</h1><div><h4>{{ product.label }}</h4><h5>${{ product.price }} (${{ discount }} Off)</h5></div><button @click="updatePrice">Reduce Price!</button></div>
</template>
<script>
export default {data() {return {discount: 0,product: {price: 25,label: 'Blue juice',},}},methods: {updatePrice() {if (this.product.price < 1) returnthis.product.price--},},
}
</script>
Time for the nested watcher. We will watch the product object’s price, and increment the discount data prop:
是时候使用嵌套监视器了。我们将观察产品对象的价格,并递增折扣数据道具:
<script>
export default {data() {return {discount: 0,product: {price: 25,label: 'Blue juice',},}},methods: {updatePrice() {if (this.product.price < 1) returnthis.product.price--},},// 新增的代码watch: {'product.price'() {this.discount++},},
}
</script>
In this exercise, we used watchers to observe a key inside an object and then set new data with or without using the optional arguments parsed by the watcher.
在本练习中,我们使用观察者观察对象内部的键,然后使用或不使用观察者解析的可选参数设置新数据。
In the next section, we will explore how to fetch and handle data using the Vue component’s async methods.
在下一节中,我们将探讨如何使用 Vue 组件的异步方法获取和处理数据。