作用:侦听属性,响应数据(data&computed)的变化,当数据变化时,会立即执行对应函数,其属性值可以为函数、字符串、对象和数组。
函数类型中,被侦听的数据作为函数名,当数据改变时,执行 watch() 中对应的函数,该函数可以接受两个参数,第一个参数是 newVal(改动后的数据),第二个参数是 oldVal (改动前的数据),如下例
{
{ bookName }}
const vm = new Vue({
el: '#app',
data: {
bookName: '《JavaScript设计模式》'
},
watch: {
bookName(newVal, oldVal) {
console.log('newVal:', newVal)
console.log('oldVal:', oldVal)
}
}
})
【结果】在控制台改变bookName的值,打印结果如下
key 为 被侦听的数据,value 为方法名字,当被侦听的数据改变时,会执行该方法,如下例
{
{ bookName }}
const vm = new Vue({
el: '#app',
data: {
bookName: '《JavaScript设计模式》'
},
methods:{
bookNameChange(){
console.log(this.bookName);
}
},
watch: {
bookName: 'bookNameChange'
}
})
【结果】
对象类型包含3个属性,handle函数(必选),deep和immediate(可选)
handler 为被侦听的数据改变时执行的回调函数,其值类型为函数 / 字符串(函数名)
{
{ bookName }}
const vm = new Vue({
el: '#app',
data: {
bookName: '《JavaScript设计模式》',
},
watch: {
bookName: {
handler() {
console.log(this.bookName)
}
}
}
})
【结果】改变 bookName 的值,执行 handler 函数
在默认情况下,侦听器侦听对象只侦听引用的变化,只有在给对象赋值时它才能被监听到,所以需要使用 deep 选项,让其可以发现对象内部值得变化,讲 deep 得值设置为 true,那么无论该对象被嵌套得有多深,都可以被侦听到。但是当对象的属性较多时,性能开销比较大。因此可以选择只侦听对象的某个属性
【例1】
{
{ book.press }}
const vm = new Vue({
el: '#app',
data: {
book: {
bookName: '《JavaScript设计模式》',
press: '人民邮电出版社',
writer: 'Addy'
}
},
watch: {
book: {
handler() {
console.log('book.press变化了')
},
deep: true
}
}
})
【结果】
immediate 选项可以使侦听开始后立刻被调用,而不是等待侦听的数据更改后才会调用
{
{ book.press }}
const vm = new Vue({
el: '#app',
data: {
book: {
bookName: '《JavaScript设计模式》',
press: '人民邮电出版社',
writer: 'Addy'
}
},
watch: {
book: {
handler() {
console.log('handler执行了')
},
deep: true,
immediate: true
}
}
})
【结果】
将对象的属性放在字符串中当作函数名,当该对象中的该属性值发生变化时,执行回调函数
{
{ book.press }}
const vm = new Vue({
el: '#app',
data: {
book: {
bookName: '《JavaScript设计模式》',
press: '人民邮电出版社',
writer: 'Addy'
}
},
watch: {
'book.press'() {
console.log('book.press改变了')
}
}
})
【结果】
将多种不同值类型写在一个数组中,如下例
{
{ bookName }}
const vm = new Vue({
el: '#app',
data: {
bookName: '《JavaScript设计模式》'
},
methods: {
bookNameChange() {
console.log('运行bookNameChange函数')
}
},
watch: {
//字符串
// bookName:['bookNameChange']
//函数
// bookName:[function () {
// console.log('bookName改变了')
// }]
//对象
// bookName:{
// handler(){
// console.log('运行handler函数')
// },
// deep:true,
// immediate:true
// }
//全部
bookName: ['bookNameChange',
function () {
console.log('运行watch中的函数')
},
{
handler() {
console.log('运行handler函数')
},
deep: true,
immediate: true
}
]
}
})
【结果】
Vue 实例将会在实例化时调用 $watch,遍历 watch 对象的每一个属性,我们也可以利用 vm.$watch 来实现侦听,用法如下
有两种方法,第一种接收三个参数,第一个为被侦听的数据,第二个为数据改变时执行的回调函数,第三个可选,为设置的选项;第二种接受两个参数,第一个参数为被侦听的数据,第二个参数为选项对象,其中 handler 函数是数据改变时执行的回调函数,其他属性可选。
【例1】三个参数
{
{ book.bookName }}
const vm = new Vue({
el:'#app',
data:{
book:{
bookName:"《JavaScript设计模式》"
}
}
})
vm.$watch('book',function () {
console.log('bookName has changed')
},{
deep: true,
immediate:true
})
【结果】
【例2】两个参数
const vm = new Vue({
el:'#app',
data:{
book:{
bookName:"《JavaScript设计模式》"
}
}
})
vm.$watch('book',{
handler(){
console.log('bookName has changed')
},
deep:true,
immediate:false
})
【结果】
传参情况同上,举例如下
vm.$watch('book.bookName',{
handler(){
console.log('bookName has changed')
}
})
【结果】
当侦听的数据在初始不确定,由多个数据得到时,此时可以将第一个参数写成函数形式,当任何依赖的数据改变时,执行回调函数,如下
{
{ bookName }}
{
{ writer }}
const vm = new Vue({
el: '#app',
data: {
bookName: "《JavaScript设计模式》",
writer: 'Addy'
}
})
vm.$watch(function () {
// 相当于监听了一个未被定义的计算属性
return this.bookName + this.writer
},function () {
// 当bookName或者writer改变时,执行该函数
console.log('At least one of them changed')
})
【结果】
【注】在侦听器函数执行后,会返回一个取消侦听器函数, 用来停止触发回调;在带有immediate选项时,不能再第一次回调时取消侦听数据,写法如下
const vm = new Vue({
el: '#app',
data: {
bookName: "《JavaScript设计模式》",
writer: 'Addy'
}
})
//这里只能用var申明变量
var unwatch = vm.$watch('bookName',function () {
if (unwatch) { //确保unwatch存在才能调用取消侦听函数
unwatch();
}
console.log('bookName changed')
},{
immediate:true
})
【结果】
(1)两者都可以观察和响应 Vue 实例上的数据的变动
(2)watch 擅长处理的场景时:一个数据影响多个数据;计算属性擅长处理的场景是:多个数据影响一个数据;
(3)计算属性不能执行异步,因为其有返回值,是同步执行的;侦听器中可以执行异步,可以用来发送请求。
{
{ question }}
var vm = new Vue({
el: '#app',
data: {
question: '',
},
watch: {
question () {
setTimeout(() => {
alert(this.question);
}, 2000)
}
}
})