侦听属性的基本用法

watch监听属性

  1. 当被监听的属性发送变化时,回调函数自动调用,进行相关操作。
  2. 监听的属性必须是存在的,才能进行监听。
  3. 既可以监听data,也可以监听计算属性
  4. watch一般写在组件内,组件的注销watch也会随之注销。

watch的三个参数

  1. handler:其值是一个回调函数,即监听到变化时应该执行的函数。
handler(newValue, oldValue)
  1. deep:其值是true或false,确认是否深入监听,默认值为false。
  2. immediate:其值是true或false,确认是否以当前的初始值执行handler函数(一上来就执行,无需等到数据发生改变),默认值为false。

watch的两种写法

  1. 创建Vue时传入watch: {}配置项。
  2. 通过vm.$watch()监听。
<div id="room">
        <h1>
            今天天气很{{info}}
        </h1>
        <button @click="isHot = !isHot">切换天气</button>
</div>

<script>
        const vm = new Vue({
            el: '#room',
            data: {
                isHot: true
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
            },
//第一种写法
            watch: {
                info: {
                    handler(newValue, oldValue) {
                        console.log('info被修改了', newValue, oldValue)
                    }
                }
            }
        })
//第二种写法
        // vm.$watch('isHot', {
        //     handler(newValue, oldValue) {
        //         console.log('info被修改了', newValue, oldValue)
        //     }

        // })
    </script>

deep深度监听

  1. Vue中watch默认不监听对象内部值的改变。
<div id="room">
        <h1>
            今天天气很{{info}}
        </h1>
        <button @click="isHot = !isHot">切换天气</button>
    </hr>
    <h3>a的值是:{{number.a}}</h3>
    <button @click="number.a++">点击a+1</button>
</div>

<script>
        const vm = new Vue({
            el: '#room',
            data: {
                isHot: true,
                number: {
                    a: 1
                }
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch: {
                number: {
		//此时点击btn使a++,number.a改变了,但无法触发监听器
                   handler(newValue, oldValue) {
                    console.log('number改变了')
                   }
                }
            }
        })
</script>

解决方法一(字符串形式)

<div id="room">
        <h1>
            今天天气很{{info}}
        </h1>
        <button @click="isHot = !isHot">切换天气</button>
    </hr>
    <h3>a的值是:{{number.a}}</h3>
    <button @click="number.a++">点击a+1</button>
</div>

<script>
        const vm = new Vue({
            el: '#room',
            data: {
                isHot: true,
                number: {
                    a: 1
                }
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch: {
		//将number写成number.a,必须加上引号
                'number.a': {
                   handler(newValue, oldValue) {
                    console.log('number改变了')
                   }
                }
            }
        })
</script>

虽然这样能解决问题,但是如果number不止a一个属性,有100个,1000个怎么办?如果都写的话代码量就会很大,此时就出现了deep深度监听。

解决方法二(deep)

<div id="room">
        <h1>
            今天天气很{{info}}
        </h1>
        <button @click="isHot = !isHot">切换天气</button>
    </hr>
    <h3>a的值是:{{number.a}}</h3>
    <button @click="number.a++">点击a+1</button>
</div>

<script>
        const vm = new Vue({
            el: '#room',
            data: {
                isHot: true,
                number: {
                    a: 1
                }
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch: {
		 number: {
                   deep: true,
                   handler(newValue, oldValue) {
                    console.log('number改变了')
                   }
                }
            }
        })
</script>

这个时候就可以使用deep深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样消耗过大。
如果监听的属性很少,那么使用字符串形式是比较合理的,监听的属性过多时,使用deep进行深度监听。

watch简写

当监听属性除了handler没有其它配置项时,可以进行简写。

<script>
//第一种简写形式
new Vue({
...
	watch: {
    	       isHot(newValue, oldValue) {
        	       console.log('isHot被修改了', newValue, oldValue)
           	}
       	}
...
})
//第二种简写形式
 vm.$watch('isHot', function(newValue, oldValue) {
            console.log('isHot被修改了', newValue, oldValue)
        })
</script>

计算属性VS侦听属性

  1. computed能完成的,watch都能完成。
  2. watch能完成的,computed不一定能完成,例如watch可以进行异步操作(在合适的场景加入异步操作能交互效果更佳)。
<!-- 姓名案例 -->
<div id="room">
        姓:<input type="text" v-model="firstName"></br>
        名: <input type="text" v-model="lastName"></br>
        姓名:<span>{{fullName}}</span>
</div>

使用计算属性实现

new Vue({
            el: '#room',
            data: {
                firstName: 'R',
                lastName: 'cloud'
            },
            computed: {
                //一般只读取属性值而不修改,所以简写只读取属性值
                fullName() {
                    return this.firstName + '-' + this.lastName
                }

            }
        })

使用监听属性实现

new Vue({
        el: '#room',
        data: {
            firstName: 'R',
            lastName: 'cloud',
            fullName: 'R-cloud'
        },
       watch: {
    // (newValue, oldValue)只写一个参数时默认是newValue
    // 监听实现可以加入异步任务,例如修改完姓一秒后再显示
           firstName(val) {
               setTimeout(()=> {
                   this.fullName = val +  '-' + this.lastName
               }, 1000)
           },
           lastName(val) {
               this.fullName = this.firstName + '-' + val
           }
        }
})