vue侦听器

作者: 踏莎行 | 来源:发表于2021-05-18 21:47 被阅读0次

      侦听器与计算属性有些相似,都是当他们的依赖项发生变化时触发,不同的时计算属性是这个值不存在,需要根据已有属性计算得来,侦听器顾名思义就是监视已经存在的值。计算属性不能有异步程序,侦听器中可以存在异步方法。能用computed的场合都能用watch解决,但是能用watch解决的,computed不一定能解决

    第一种写在创建vue的实例的配置对象中
    • 简单的侦听器
      语法:
    要监听的属性: function(newVal, oldVal){
      逻辑
    }
    
    /**
     * newVal : 就是你修改的新值
     * oldVal: 旧的值
     */
    

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div id="app">
                <input v-model="a1" type="" name="" id="" value="" />
                <input v-model="a2" type="" name="" id="" value="" />
                <div>a1 + a2 的值是 {{num}}</div>
    
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            a1: 2,
                            a2: 3,
                            num: ''
                        }
                    },
                    
                    watch:{
                        a1: function(newVal, oldVal){
                            console.log(typeof newVal);
                            this.num = newVal + this.a2
                        }
                    }
                })
            </script>
        </body>
    </html>
    

    此时效果是


    Snipaste_2021-05-18_20-42-52.png

    修改a1的值之后,就会立刻执行侦听器的函数,计算num的值


    Snipaste_2021-05-18_20-44-33.png
    • 复杂的侦听器
      上面的例子中,num的初始值为空,所以页面上没有显示出num的值,这样的体验就不好,所以引出一个配置:immediate
      语法:
    要监听的属性:{
      handler(newVal, oldVal){
    
      },
      immediate: true
    }
    
    /**
        newVal : 就是你修改的新值
        oldVal: 旧的值
        handler: 名字固定,默认
        immediate:当取值为true时,无论被监视的属性发不发生变化,都会强制执行一次回调
    */
    

    将上面的例子修改之后就是:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div id="app">
                <input v-model="a1" type="" name="" id="" value="" />
                <input v-model="a2" type="" name="" id="" value="" />
                <div>a1 + a2 的值是 {{num}}</div>
    
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            a1: 2,
                            a2: 3,
                            num: 0
                        }
                    },
                    
                    watch:{
                        a1: {
                            handler(newVal, oldVal){
                                this.num = newVal + this.a2
                            },
                            
                            immediate: true
                        }
                    }
                })
            </script>
        </body>
    </html>
    

    页面一打开,num就已经显示出来了


    Snipaste_2021-05-18_20-56-56.png
    • 深度监听
      上面的例子只是监听了普通的数据,当监听对象或者数组时,就会出现问题,对象的属性或者数组元素发生变化时,侦听器就见听不到了,所以需要使用深度监听,只需要添加一个deep属性即可
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div id="app">
                <div>{{obj.name}}</div>
                <input v-model="obj.name" type="" name="" id="" value="" />
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            obj: {
                                name: '张三'
                            }
                        }
                    },
                    
                    watch:{
                        obj: {
                            handler(newVal, oldVal){
                                console.log("名字发生变化" + newVal);
                            },
                            
                            deep: true
                        }
                    }
                })
            </script>
        </body>
    </html>
    

    :不能直接去监听对象的某个属性或者数组的某个元素,语法不通过的,如

    watch:{
        arr[0]: {
    
        }
    }  // 不可以
    
    watch:{
        obj.name: {
    
        }
    }  // 不可以
    
    • 监听对象的某一个属性
      将obj.xxx加上引号 => 'obj.xxx'
    'obj.name': {
      handler(newVal, oldVal){
        console.log("名字发生变化" + newVal);
      },
      deep: true
    }
    

    完整程序

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div id="app">
                <div>{{obj.name}}</div>
                <input v-model="obj.name" type="" name="" id="" value="" />
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            obj: {
                                name: "张三"
                            }
                        }
                    },
                    
                    watch:{
                        'obj.name': {
                            handler(newVal, oldVal){
                                console.log("名字发生变化" + newVal);
                            },
                            
                            deep: true
                        }
                    }
                })
            </script>
        </body>
    </html>
    

    这样就能修改成功了


    Snipaste_2021-05-18_21-18-52.png
    • 监听数组的某一个元素
      如果使用监听对象某一个属性那样监听数组的某一个元素就会报错

    Failed watching path: "arr[0]" Watcher only accepts simple dot-delimited paths. For full control, use a function instead.
    翻译过来就是: 监视路径失败:“arr[0]”监视程序只接受简单的点分隔路径。要完全控制,请改用函数。

    所以这里我们就可以使用计算属性,将arr[0]做成计算属性,再监听这个计算属性就ok了

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div id="app">
                <div>{{arr[0]}}</div>
                <input v-model="arr[0]" type="" name="" id="" value="" />
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            arr: ['1', '2']
                        }
                    },
                    
                    watch:{
                        arrFirst: {
                            handler(newVal, oldVal){
                                console.log("名字发生变化" + newVal);
                            },
                            
                            deep: true
                        }
                    },
                    
                    computed:{
                        arrFirst(){
                            return this.arr[0]
                        }
                    }
                })
            </script>
        </body>
    </html>
    
    Snipaste_2021-05-18_21-31-20.png
    • 数组形式(vue3+)
      这种方式就比较灵活了,
    watch: {
      (监听的数据):[处理函数1, 处理函数2, .........]
    }
    

    也就说我们通过数组的形式,可以为当前监听的数据添加多个处理函数,也可以直接调用methods中的方法,不过要引号将函数名引起来

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      <div id="app">
        <h1>{{name}}</h1>
        <button @click="changeName">改名字</button>
      </div>
      <script src="./js/vue2.js"></script>
      <script>
        var vm = new Vue({
          el: "#app",
          data() {
            return {
              name: "zhangsan"
            }
          },
          methods: {
            test(){
              console.log("我是test");
            },
    
            changeName(){
              this.name = "王五"
            }
          },
    
          watch: {
            name:[
              'test',
              function(newVal, old){
                console.log("-----------------名字改了------------------------");
              }
            ]
          }
        })
      </script>
    </body>
    
    </html>
    
    第二种写在全局
    <!DOCTYPE html>
    <html>
        <head>
        ...
        </head>
        <body>
            <div id="app">
                ...
            </div>
            <script src="./vue.js" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript">
                const vm = new Vue({
                    el: '#app',
                    data() {
                        return {
                            name: "张三"
                        }
                    }
                })
                vm.$watch("name", function(newVal, oldVal){
                      // 你的逻辑
                })
            </script>
        </body>
    </html>
    

    强调

    不论是写在配置对象还是全局,侦听器的回调函数都不能用箭头函数,因为箭头函数的this在当前环境指向的是window,当你使用this时就可能没反应或者报错

    相关文章

      网友评论

        本文标题:vue侦听器

        本文链接:https://www.haomeiwen.com/subject/bdvyjltx.html