小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Vue 通过 watch 选项来侦听属性的变化,watch 选项中可以编写 watchers(侦听器),每个 watcher 都能侦听到当前活动的实例上对应的数据的变化。
- 什么是侦听器呢?
- 开发中我们在
data返回的对象中定义了数据,这个数据通过插值语法等方式绑定到template中; - 当数据发生变化时,
template会自动进行更新来显示最新的数据; - 但是在某些情况下,我们希望在代码逻辑中监听某个数据的变化,这个时候就需要通过
watch选项用侦听器(watchers) 来完成了;
- 开发中我们在
- 侦听器的用法如下:
- 选项:
watch - 类型:
{ [key: string]: string | Function | Object | Array }(即watch是一个对象,对象中的key要求是string类型,key对应的value可以是string类型或Function类型或Object类型或Array类型)
- 选项:
1. 侦听器基础使用案例
比如用户在 input 中输入一个问题,我们希望根据输入的问题去服务器查询答案。
- 第一种方式是我们再提供一个查询按钮,用户输入完问题后点击按钮向服务器发送网络请求查询答案。
- 第二种方式是不提供查询按钮,但每当用户输入了最新的内容,我们就获取到最新的内容,并使用该内容(问题)去服务器查询答案,也就是说我们要实时地获取最新的数据。
第一种方式(<body> 元素中)代码如下:
<div id="app"></div>
<template id="my-app">
您的问题:<input type="text" v-model="question">
<button @click="searchAnswer">查找答案</button>
<p>{{ result }}</p>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
data() {
return {
question: '谁是最可爱的人',
answer: '',
result: ''
}
},
methods: {
searchAnswer() {
// 向服务器发送网络请求,查找答案
// ...
// 把服务器返回的答案保存到变量中
this.answer = '服务器返回的答案'
this.result = `问题“${this.question}”的答案是:${this.answer}`;
}
},
template: '#my-app'
};
Vue.createApp(App).mount('#app');
</script>
页面效果:
上面这种方式中必须点击按钮才会去查找答案,那如果现在的需求是只要用户在 input 中输入了内容,就立刻根据最新的内容去查找答案呢?也就是说我们需要监听 input 中数据的变化,只要其中的数据发生变化就会去查找答案,而不需要再去点击按钮查找。
- 这时候我们就需要(在代码逻辑中)侦听
data中question的变化了。- 在第一种方式中,侦听
data中question的变化是交给Vue的响应式系统完成的,响应式系统侦听到变化后会更新template中的内容(页面内容); - 而现在,我们需要在侦听
data中question的变化时,去进行一些逻辑的处理(如网络请求),而逻辑处理通常是通过JavaScript代码实现的,也就是说我们需要在JavaScript代码中的某个地方去侦听question的变化,怎么侦听呢?这时我们就可以在watch选项中进行侦听了。
- 在第一种方式中,侦听
第二种方式(<body> 元素中)代码如下:
<div id="app"></div>
<template id="my-app">
您的问题:<input type="text" v-model="question">
<!-- <button @click="searchAnswer">查找答案</button> -->
<p>{{ result }}</p>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
data() {
return {
question: '谁是最可爱的人',
answer: '',
result: ''
}
},
watch: {
// question:要侦听的数据(data 中返回的对象的属性名称,或者 computed 属性,
// 当然,还可以侦听 props(用来实现组件之间数据的传递,后面会讲))
// newValue:变化后的新值
// oldValue:变化前的旧值
question(newValue, oldValue) {
console.log('新值:', newValue, '旧值:', oldValue);
this.searchAnswer(newValue);
// 真实开发中可能会使用 axios 发送网络请求:
// axios.get({
// // ...
// });
// 后面我们也会对 axios 进行讲解、封装
}
},
methods: {
searchAnswer(newValue) {
// 向服务器发送网络请求,查找答案
// ...
// 把服务器返回的答案保存到变量中
this.answer = '服务器返回的答案'
// this.result = `问题“${this.question}”的答案是:${this.answer}`;
this.result = `问题“${newValue}”的答案是:${this.answer}`;
}
},
template: '#my-app'
};
Vue.createApp(App).mount('#app');
</script>
页面效果:
因为 input 元素上用 v-model 做了双向绑定(后面讲 v-model 时会讲),所以当 input 中的内容发生变化时,data 中的 question 也会同步变化,而由于我们在 watch 中编写了对 question 的侦听,所以 question 发生变化时,就会执行 question 侦听器中的代码。
总结:当我们想要侦听比如说
data中的数据,当它发生变化时,我们想进行一些逻辑处理的时候,一般就会使用侦听器;但如果只是页面中的数据(template中的数据),它本身就能对数据的变化进行响应,不需要使用侦听器。