Vue属性篇_侦听器watch

作用:侦听属性,响应数据(data&computed)的变化,当数据变化时,会立即执行对应函数,其属性值可以为函数、字符串、对象和数组。

1.属性值类型

(1)函数类型

函数类型中,被侦听的数据作为函数名,当数据改变时,执行 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的值,打印结果如下

Vue属性篇_侦听器watch_第1张图片

(2)字符串类型

key 为 被侦听的数据,value 为方法名字,当被侦听的数据改变时,会执行该方法,如下例

{ { bookName }}
const vm = new Vue({
    el: '#app',
    data: {
        bookName: '《JavaScript设计模式》'
    },
    methods:{
        bookNameChange(){
            console.log(this.bookName);
        }
    },
    watch: {
        bookName: 'bookNameChange'
    }
})

【结果】

Vue属性篇_侦听器watch_第2张图片

(3)对象类型

对象类型包含3个属性,handle函数(必选),deep和immediate(可选) 

1)handler

handler 为被侦听的数据改变时执行的回调函数,其值类型为函数 / 字符串(函数名)

{ { bookName }}
const vm = new Vue({
    el: '#app',
    data: {
        bookName: '《JavaScript设计模式》',
    },
    watch: {
        bookName: {
            handler() {
                console.log(this.bookName)
            }
        }
    }
})

【结果】改变 bookName 的值,执行 handler 函数

Vue属性篇_侦听器watch_第3张图片

2)deep 

在默认情况下,侦听器侦听对象只侦听引用的变化,只有在给对象赋值时它才能被监听到,所以需要使用 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
        }
    }
})

【结果】

Vue属性篇_侦听器watch_第4张图片

3)immediate

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
        }
    }
})

【结果】

 4)只侦听对象的某个属性

将对象的属性放在字符串中当作函数名,当该对象中的该属性值发生变化时,执行回调函数

{ { book.press }}
const vm = new Vue({
    el: '#app',
    data: {
        book: {
            bookName: '《JavaScript设计模式》',
            press: '人民邮电出版社',
            writer: 'Addy'
        }
    },
    watch: {
        'book.press'() {
            console.log('book.press改变了')
        }
    }
})

【结果】

(4)数组类型

将多种不同值类型写在一个数组中,如下例

{ { 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_第5张图片

2.vm.$watch

Vue 实例将会在实例化时调用 $watch,遍历 watch 对象的每一个属性,我们也可以利用 vm.$watch 来实现侦听,用法如下

(1)侦听某个数据

有两种方法,第一种接收三个参数,第一个为被侦听的数据,第二个为数据改变时执行的回调函数,第三个可选,为设置的选项;第二种接受两个参数,第一个参数为被侦听的数据,第二个参数为选项对象,其中 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
})

 【结果】

Vue属性篇_侦听器watch_第6张图片

【例2】两个参数

const vm = new Vue({
    el:'#app',
    data:{
        book:{
            bookName:"《JavaScript设计模式》"
        }
    }
})
vm.$watch('book',{
    handler(){
        console.log('bookName has changed')
    },
    deep:true,
    immediate:false
})

 【结果】

Vue属性篇_侦听器watch_第7张图片

(2)侦听某个对象属性

传参情况同上,举例如下

vm.$watch('book.bookName',{
    handler(){
        console.log('bookName has changed')
    }
})

【结果】 

Vue属性篇_侦听器watch_第8张图片

(3) 侦听数据由多个数据得到

当侦听的数据在初始不确定,由多个数据得到时,此时可以将第一个参数写成函数形式,当任何依赖的数据改变时,执行回调函数,如下

{ { 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')
})

【结果】

Vue属性篇_侦听器watch_第9张图片

【注】在侦听器函数执行后,会返回一个取消侦听器函数, 用来停止触发回调;在带有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
})

 【结果】

Vue属性篇_侦听器watch_第10张图片

 3.侦听器与计算属性比较

(1)两者都可以观察和响应 Vue 实例上的数据的变动

(2)watch 擅长处理的场景时:一个数据影响多个数据;计算属性擅长处理的场景是:多个数据影响一个数据;

(3)计算属性不能执行异步,因为其有返回值,是同步执行的;侦听器中可以执行异步,可以用来发送请求。

{ { question }}
var vm = new Vue({
  el: '#app',
  data: {
    question: '',
  },
  watch: {
    question () {
      setTimeout(() => {
        alert(this.question);
      }, 2000)
    }
  }
})

你可能感兴趣的:(Vue,vue)