侦听器

什么是侦听器?

  • 开发中我们在data返回的对象中定义了数据,这个数据通过 mustache 语法等方式绑定到 template 模板中
  • 当数据发生变化,template 会自自动更新来显示最新的数据
  • 于是,在某些情况下,我们需要在发生数据变化时,执行一些业务逻辑。这个时候就需要侦听器watch来完成了

侦听器的用法:

  • 选项:watch
  • 类型:{[key: string]: string | Function | Object | Array}

侦听器案例

比如,当用户输入时我们把用户输入的内容实时的发送到后端。

<template id="my-app">
    你的问题:<input type="text" v-model="question">
    
</template>
<script src="../js/vue.js"></script>
<script>
    const App = {
        template: '#my-app',
        data() {
            return {
                // 侦听question的变化,去进行一些逻辑的处理
                question: 'Hello world'
            };
        },
        watch: {
            // question 是侦听data中的属性名称
            // newValue 变化后的值
            // oldValue 变化前的值
            question(newValue, oldValue) {
		// 写数据发生变化的业务逻辑
                console.log(newValue, oldValue);
                this.queryQuestion();
            }
        },
        methods: {
            queryQuestion() {
                console.log("查找答案");
            }
        }
    }
    Vue.createApp(App).mount("#app");
</script>

侦听器watch的配置选项

  • 如果我们侦听的是个对象,当对象内部属性发生变化的时候并不会侦听到。
  • 因为,默认情况下,watch只侦听 对应的引用值的变化,对内部属性变化不会做出响应的.
    • 可以通过配置,deep: true。 来开启深度侦听
  • 默认情况下,侦听器只有当数据发生改变的时候才触发侦听。但是,如果我们想它在一开就执行一下默认的逻辑。
    • 可以通过 immediate:true,来开启立即执行一次。
<template id="my-app">
    <h1>{{info}}</h1>
    <button @click="changeInfo">改变数据本身</button>
    <button @click="changeInfoName">改变数据内部</button>
</template>
<script src="../js/vue.js"></script>
<script>
    const App = {
        template: '#my-app',
        data() {
            return {
                info: {
                    name: 'sdf',
                    age: 18
                }
            };
        },
        watch: {
            // 默认情况下只能侦听数据本身的改变(不能侦听数据内部的
            // info(newValue, oldValue) {
            //     console.log("newValue:", newValue, "oldValue:", 
            // }
            // 深度侦听/立即执行(一定会执行一次)
            info: {
                handler: function(newInfo, oldInfo) {
                    console.log("newValue:", newInfo, "oldValue:", 
                },
                // 设置深度侦听
                deep: true,
                // 立即执行
                immediate: true
            }
        },
        methods: {
            changeInfo() {
                this.info = {name: "kobe"}
            },
            changeInfoName() {
                this.info.name = "kobe";
            }
        }
    }
    Vue.createApp(App).mount("#app");
</script>

添加多个侦听器和侦听对象中的某个属性

  • 当某个数据需要有多个侦听器的时候,使用数组将侦听器包裹。每个侦听器可以单独配置。也可以直接写成一个函数,它们会被依次调用。
  • 当需要单独侦听对象中的某个属性时,"obj.property: method"
<template id="my-app">
    <h1>{{info}}</h1>
    <button @click="changeInfo">改变数据本身</button>
    <button @click="changeInfoName">改变数据内部</button>
    <h2>{{f}}</h2>
    <input type="text" v-model="f" placeholder="修改f的值">
</template>
<script src="../js/vue.js"></script>
<script>
    const App = {
        template: '#my-app',
        data() {
            return {
                info: {
                    name: 'sdf',
                    age: 18
                },
                f: "sssss",
            };
        },
        watch: {
            "info.name": function(newValue, oldValue) {
                console.log(newValue, oldValue);
            },
            info: [
                function handle1(val, oldVal) {
                    console.log("handler1 triggred")
                },
                function handler2(val, oldVal) {
                    console.log("handle2 triggred");
                },
                {
                    handler: function handle3(val, oldVal) {
                        console.log("handle3 triggred")
                    },
                    deep: true,
                    immediate: true
                }
            ]
        },
        methods: {
            changeInfo() {
                this.info = {name: "kobe"}
            },
            changeInfoName() {
                this.info.name = "kobe";
            }
        },
        created() {
	// 动态添加
            this.$watch("info", (newInfo, oldInfo)=>{
                console.log(newInfo, oldInfo);
            }, {
                deep: true,
                immediate: true
            });
        }
    }
    Vue.createApp(App).mount("#app");
</script>
  • 当f被修改后image.png

动态添加侦听器

在created生命周期中,使用 this.$watch() 来监听

  • 第一个参数为侦听的源
  • 第二个参数是要侦听的回调函数 callback
  • 第三个参数是额外的其他配置,deep、immediate
created() {
    this.$watch("info", (newInfo, oldInfo)=>{
        console.log(newInfo, oldInfo);
    }, {
        deep: true,
        immediate: true
    });
}