一 侦听响应式ref
侦听响应式ref常量,当常量的ref的value值发生改变时会触发watch
一个小栗子:当输入框的输入内容变化时下方的文本也会跟着改变
<template>
<div class="box content">
<div class="intro">
<el-input v-model="input" @change="inputChange"></el-input>
</div>
<div class="intro">
<el-text>{{ message }}</el-text>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance().proxy;
const input = ref("");
const message = ref("");
watch(input, (newValue, oldValue) => {
message.value = "input值发生了变化,newValue = " + newValue + ", oldValue = " + oldValue;
});
/** 事件回调 */
const inputChange = () => {
console.log("input value = ", input.value);
}
</script>
<style scoped lang="less">
.box{
display: flex;
flex-direction: column;
margin: 10px;
padding: 15px;
.intro{
padding: 20px;
}
}
</style>
二 监听reactive响应式对象
系统默认是深层监听,当响应式对象的属性发生改变时,会触发watch
一个小栗子:当点击一次primary按钮时,可以看到cmpNum的count会加3
<template>
<div class="box content">
<div class="intro">
<el-button type="primary" @click="cmpNumChange">cmpNum.count = {{ cmpNum.count }}</el-button>
</div>
<div class="intro">
<el-text>{{ cmpMsg }}</el-text>
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance().proxy;
const cmpNum = reactive({count: 0});
const cmpMsg = ref("");
// 监听reactive响应式对象,系统默认是深层监听,当响应式对象的属性发生改变时,会触发watch
// 当点击一次primary按钮时,可以看到cmpNum的count会加3
watch(cmpNum, (newValue, oldValue) => {
cmpMsg.value = "cmpNum.cout = " + cmpNum.count;
});
// 注:当监听响应式对象时,不能直接监听响应式对象的value
watch(
() => cmpMsg.value,
(value) => {
console.log("watch cmpMsg value = ", value);
}
)
/** 事件回调 */
const cmpNumChange = () => {
cmpNum.count = cmpNum.count + 2;
console.log("cmpNum.value = ", cmpNum.count);
}
</script>
<style scoped lang="less">
.box{
display: flex;
flex-direction: column;
margin: 10px;
padding: 15px;
.intro{
padding: 20px;
}
}
</style>
三 深层侦听器
直接给 watch()
传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发
一个小栗子 :当点击button时,会在回调事件中改变person的属性,从而触发侦听器watch
在使用时,主要是在代码中加入:{deep: true}
<template>
<div class="box content">
<div class="intro">
<el-button type="primary" @click="changePersonName">person name is {{ state.person.name }}</el-button>
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
import { getCurrentInstance } from 'vue';
const person = {name: "Pem", age: 20};
const state = ref({person: person});
// 使用deep:true属性,进行对象的深层监听
watch (
() => state.value.person,
(newValue, oldValue) => {
console.log("deep newValue = ", newValue);
console.log("deep oldValue = ", oldValue);
},
{deep: true}
)
/** 事件回调 */
const changePersonName = () => {
state.value.person.name = input.value + ".Pem";
}
</script>
<style scoped lang="less">
.box{
display: flex;
flex-direction: column;
margin: 10px;
padding: 15px;
.intro{
padding: 20px;
}
}
</style>
四 即时回调的侦听器
watch在默认情况下是懒加载的,仅在数据源发生变化时才会触发。但在某些场景下,我们希望在创建watch时立即执行一次回调。
我们可以通过传入 immediate: true
选项来强制侦听器的回调立即执行。
一个小栗子:
<template>
<div class="box content">
<div class="intro">
<el-input v-model="immediateInput"></el-input>
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
const immediateInput = ref("");
// 即使回调的侦听器
/*
watch默认是懒执行的:仅当数据变化时,才会执行回调。但在某些场景中,我们希望在创建某些侦听器时,
立即执行一遍回调。举例来说,我们想请求一些初始数据,然后在相关状态更改时重新请求数据
在下面的例子中,可以看到在页面第一次渲染出来后就可以看到在watch中设置的初始值,说明这个watch
被执行了一次
*/
watch (
() => immediateInput.value,
(newValue, oldValue) => {
console.log("new value = ", newValue);
if (newValue === "") {
getStartValue();
}
},
{immediate: false} //这里需要加入这句
)
function getStartValue(){
immediateInput.value = "start base value";
console.log("getStartValue");
}
</script>
<style scoped lang="less">
.box{
display: flex;
flex-direction: column;
margin: 10px;
padding: 15px;
.intro{
padding: 20px;
}
}
</style>