watch 是 Vue 2 中的一个重要选项,用于定义观察者(watcher),监视指定的数据属性的变化。当被监视的属性发生变化时,相应的处理函数会被调用,从而允许你对变化做出反应。这在需要根据数据变化执行异步操作或开销较大的计算时非常有用。
watch 的基本语法如下:
如果监听的需求比较简单,可以直接使用函数式写法:
export default {
data() {
return {
message: 'Hello, Vue!'
}
},
watch: {
// 定义一个 watcher 来监视 message 属性
message (newValue, oldValue) {
console.log(`message changed from ${oldVal} to ${newValue}`)
}
}
}
在这个例子中,每当 message 的值发生变化时,watch 选项中的处理函数就会被触发,并接收新旧两个值作为参数。这种方式写起来简便,适用于简单的监听需求
如果监听需求比较复杂,建议使用对象式写法:、
export default {
data() {
return {
dataProperty: ''
};
},
watch: {
dataProperty: {
handler(newVal, oldVal) {
console.log(`数据从 ${oldVal} 变更为 ${newVal}`);
},
deep: true,
immediate: true
}
}
};
这种方式更清晰,更方便拓展和维护,适用于复杂的监听需求
假设我们有一个简单的输入框,希望在用户输入内容后立即更新某个状态:
<template>
<div id="app">
<input v-model="searchText" placeholder="Search...">
<p>Searching for: {{ searchText }}</p>
</div>
</template>
<script>
export default {
data() {
return {
searchText: ''
};
},
watch: {
searchText(newValue) {
console.log('Search text changed:', newValue);
this.performSearch(newValue);
}
},
methods: {
performSearch(query) {
// 执行搜索逻辑...
console.log('Performing search with query:', query);
}
}
};
</script>
这段代码会在每次 searchText 变化时打印新的值,并调用 performSearch 方法来执行搜索操作。
如果你需要监听的对象是嵌套的,或者是一个复杂的数据结构,默认情况下 watch 只会监听顶层属性的变化。为了监听对象内部属性的变化,可以使用 deep 选项:
export default {
data() {
return {
user: {
name: 'John Doe',
age: 30
}
};
},
watch: {
user: {
handler(newVal, oldVal) {
console.log('User object changed:', newVal);
},
deep: true // 开启深度监听
}
}
};
在这个例子中,无论 user 对象中的 name 还是 age 发生变化,都会触发 watch 处理函数
注意事项: 开启深度监听后,需要写 handler()方法。如果没有设置 deep,当对象内部的属性变化时,处理函数不会被触发。
有时候你可能希望在组件初始化时就执行一次 watch 的处理函数。为此,可以设置 immediate 选项为 true
export default {
data() {
return {
message: 'Initial message'
};
},
watch: {
message: {
handler(newVal) {
console.log('Message changed:', newVal);
},
immediate: true // 初始化时立即执行一次
}
}
};
这段代码会在组件实例创建之初就打印出 message 的初始值
当某个数据发生变化时,可能需要执行一些异步操作,比如发送网络请求。
<template>
<div>
<input v-model="keyword" placeholder="请输入关键词">
<ul>
<li v-for="item in searchResults" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keyword: '',
searchResults: []
};
},
watch: {
keyword(newVal) {
// 模拟异步搜索请求
this.fetchSearchResults(newVal);
}
},
methods: {
async fetchSearchResults(keyword) {
try {
// 这里的请求地址只是示例,无法使用
const response = await fetch(`https://api.example.com/search?keyword=${keyword}`);
const data = await response.json();
this.searchResults = data;
} catch (error) {
console.error('搜索出错:', error);
}
}
}
};
</script>
在上述代码中,watch 监听 keyword 的变化,当 keyword 改变时,会调用 fetchSearchResults 方法发送异步请求并更新搜索结果。
注意事项: 如果进行网络请求,建议进行防抖操作,避免过度多次请求给服务器造成更大的压力。
当一个数据的变化依赖于另一个数据,并且需要进行复杂计算时,可以使用 watch 来实现数据同步。
<template>
<div>
<input v-model="price" type="number" placeholder="请输入价格">
<input v-model="quantity" type="number" placeholder="请输入数量">
<p>总价: {{ totalPrice }}</p>
</div>
</template>
<script>
export default {
data() {
return {
price: 0,
quantity: 0,
totalPrice: 0
};
},
watch: {
price(newPrice) {
this.totalPrice = newPrice * this.quantity;
},
quantity(newQuantity) {
this.totalPrice = this.price * newQuantity;
}
}
};
</script>
这里 watch 监听 price 和 quantity 的变化,当它们其中一个发生变化时,会重新计算 totalPrice。
当需要监听对象或数组的变化时,可以使用 watch 的深度监听功能。
<template>
<div>
<button @click="addItem">添加商品</button>
<ul>
<li v-for="item in shoppingCart" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
shoppingCart: []
};
},
watch: {
shoppingCart: {
handler(newCart) {
console.log('购物车发生变化:', newCart);
},
deep: true
}
},
methods: {
addItem() {
this.shoppingCart.push({ id: Date.now(), name: '商品' + Date.now() });
}
}
};
</script>
在这个例子中,使用 deep: true 开启深度监听,当 shoppingCart 数组的内容发生变化时,会触发 handler 函数。
除了更新数据,watch 还可以用于执行一些副作用操作,比如修改 DOM 元素的样式。
<template>
<div>
<input v-model="isActive" type="checkbox">
<div :class="{ active: isActive }">这是一个可激活的区域</div>
</div>
</template>
<script>
export default {
data() {
return {
isActive: false
};
},
watch: {
isActive(newVal) {
if (newVal) {
// 执行一些额外的副作用操作
console.log('激活状态已开启');
} else {
console.log('激活状态已关闭');
}
}
}
};
</script>
当 isActive 的值发生变化时,会在控制台输出相应的信息,同时修改 DOM 元素的样式。
在表单输入过程中,当用户输入内容发生变化时,可能需要实时进行表单验证。使用 watch 可以方便地监听表单字段的变化并执行相应的验证逻辑。
<template>
<div>
<input v-model="email" placeholder="请输入邮箱">
<p v-if="emailError">{{ emailError }}</p>
</div>
</template>
<script>
export default {
data() {
return {
email: '',
emailError: ''
};
},
watch: {
email(newEmail) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(newEmail)) {
this.emailError = '请输入有效的邮箱地址';
} else {
this.emailError = '';
}
}
}
};
</script>
在上述代码中,watch 监听 email 的变化,每当用户输入新内容时,会使用正则表达式验证邮箱格式是否正确,并显示相应的错误信息。
当应用中有缓存数据,并且某个相关的数据发生变化时,需要更新缓存数据。这时可以使用 watch 来监听关键数据的变化,从而触发缓存更新操作。
<template>
<div>
<button @click="updateData">更新数据</button>
<p>当前数据: {{ mainData }}</p>
</div>
</template>
<script>
export default {
data() {
return {
mainData: '初始数据',
cachedData: '初始缓存数据'
};
},
watch: {
mainData(newData) {
// 更新缓存数据
this.cachedData = `缓存的 ${newData}`;
console.log('缓存数据已更新:', this.cachedData);
}
},
methods: {
updateData() {
this.mainData = `新数据 ${Date.now()}`;
}
}
};
</script>
这里 watch 监听 mainData 的变化,当 mainData 更新时,会相应地更新 cachedData 并在控制台输出更新信息。
当使用第三方库,且某个数据的变化需要同步到第三方库时,watch 可以发挥作用。例如,在使用地图库时,监听地图的中心点或缩放级别变化,更新地图显示。
<template>
<div id="map"></div>
<input v-model="zoomLevel" type="number" placeholder="请输入缩放级别">
</template>
<script>
import Map from 'some-map-library';
export default {
data() {
return {
zoomLevel: 10,
map: null
};
},
mounted() {
// 初始化地图
this.map = new Map('map', { zoom: this.zoomLevel });
},
watch: {
zoomLevel(newZoom) {
// 更新地图缩放级别
this.map.setZoom(newZoom);
}
}
};
</script>
在这个例子中,watch 监听 zoomLevel 的变化,当用户修改缩放级别输入框的值时,会调用地图库的 setZoom 方法更新地图的缩放级别。
在单页面应用(SPA)中,当路由发生变化时,可能需要执行一些特定的操作,比如滚动到页面顶部、重置页面状态等。可以使用 watch 监听路由的变化。
<template>
<div>
<!-- 这里是页面内容 -->
</div>
</template>
<script>
export default {
watch: {
// 当路由变化时,滚动到页面顶部
`$store` () {
window.scrollTo(0, 0)
}
}
}
</script>
在 Vue.js 中,$route 是一个响应式对象,使用 watch 监听它的变化,当路由切换时,会将页面滚动到顶部。
watch 是 Vue 2 中一个非常强大的工具,适用于需要根据数据变化执行异步操作或开销较大的计算场景。通过合理使用 watch,可以实现高效的数据响应和复杂的业务逻辑。