Vue前端框架——监视属性

发布于:2022-12-10 ⋅ 阅读:(583) ⋅ 点赞:(0)

为什么要说监视属性呢?主要是因为在 Vue2 的官方文档中并没有详细的去介绍监视属性,但是我觉得监视属性这个东西多少还是有点用的。在官方文档中监视属性被叫做侦听器。

监视(动词):指从一旁监察注视的意思。

属性(名词):事物所具有的不可缺少的性质。如,昼伏夜出,是夜行动物的属性。

在 Vue 中监视属性主要是监视页面中数据状态的变化,并且可以根据数据状态的不同而做出不同的处理。

监视属性在 Vue 中有两种写法,分别是完整形式和简写形式。完整形式写起来相对复杂,但是灵活性更高,可以做一些复杂的处理。简写形式写起来相对简单,但是灵活性差,适合做一些简单的处理。

监视属性的完整形式写法

在 Vue 中每个需要监视的属性都要在 watch 这个配置项中定义,定义的监视属性完整形式是一个键值对。键是需要监视的属性名,值是一个对象

比如在下面的代码中,data 配置项中的 isSunny 就是一个属性,我要监视这个属性,那就在 watch 配置项中按照特定的格式编写代码。

// 监视属性配置项
watch: {
    // 监视isSunny属性
    isSunny: {
        // handler函数名称是固定的,不能随意更改
        handler(newValue, oldValue) {
            console.log("new:"newValue, "old:"oldValue)
        }
    }
}

完整代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <script src="./vue.js"></script>
        <title>监视属性</title>
    </head>
    <body>
        <div id="root">
            <h2>
                今天是{{ isSunny ? "晴天,适合出去玩" : "阴天,出门记得带伞!" }}
            </h2>
            <button @click="changeWeather">切换天气</button>
        </div>
        <script>
            Vue.config.productionTip = false
            new Vue({
                el: "#root",
                data: {
                  isSunny: true
                },
                // 方法配置项
                methods: {
                    // 按钮点击触发此方法
                    changeWeather() {
                        this.isSunny = !this.isSunny
                    }
                },
                // 监视属性配置项
                watch: {
                    // 监视isSunny属性
                    isSunny: {
                        // handler函数名称是固定的,不能随意更改
                        handler(newValue, oldValue) {
                            console.log("new:"newValue, "old:"oldValue)
                        }
                    }
                }
            })
         </script>
    </body>
</html>

代码运行后在浏览器中成功的显示了出来,此时我还没有点击页面中的按钮。因为如果我点击按钮的话,右侧控制台会显示代码的输出内容,而此时控制台是空的。

现在尝试点击两次页面中的按钮,可以看到控制台进行了两次输出,而输出结果正是由 isSunny 这个监视属性中 handler 函数进行输出的。

分析这两次输出的结果

第一次:点击按钮后触发 changeWeather方法,isSunny 属性的值改变了。在监视属性中检测到了 isSunny 值的变化,从而触发 handler 函数,该函数接收两个参数。第一个参数是被监视的属性变化后的值,第二个参数是被监视的属性变化前的值。

isSunny 属性在未点击按钮之前的值是 true,点击按钮之后值变成了 false,所以第一次输出 new: false(新值是 false)old: true(旧值是true)

第二次:逻辑和第一次的一样,之不过值发生了变化。

immediate配置

在监视属性的完整形式中,除了 handler 这个配置项外,还有两个常用的配置项,分别是 immediate 和 deep,先来看 immediate。

immediate 的作用主要是可以让 handler 函数在页面渲染完成之后立即执行,不再需要函数值改变后再执行。immediate 这个单词中文翻译后也有即时、立刻的意思。

// 监视属性配置项
watch: {
    // 监视isSunny属性
    isSunny: {
        // immediate表示在页面渲染完成后立即执行handler函数,默认值为false
        immediate: true,
        // handler函数名称是固定的,不能随意更改
        handler(newValue, oldValue) {
            console.log("new:"newValue, "old:"oldValue)
        }
    }
}

在 isSunny 监视属性中添加 immediate 这个配置然后直接运行程序,注意此时我并没有点击页面中的按钮,但控制台却输出了一条内容,证明 isSunny 监视属性的  handler 函数被 immediate 触发了。

由于页面也只是刚刚渲染完成,所以被监视的 isSunny 属性并没有进行状态变化,那也就很好的解释了控制台输出的 newValue 是 isSunny 的初始值 true,而 oldValue 由于不存在所以默认值为 undefined。

 

deep配置

deep 配置项在监视属性中起到深度监视的作用,默认值为 false。意思是可以监视多层次的数据,比如对象和数组这种多层次的数据结构。如果监视属性中不添加 deep  配置,恰好这个属性又是一个对象类型的数据,那么在修改对象中任何一个值的时候,都不会触发监视属性中的 handler 函数。

接下来在原来的代码中添加一些代码来看看 deep 这个配置项的作用

在 DOM 结构中添加

<h2>深度监视</h2>
<h3>x的值是: {{ testNum.x }}</h3>
<button @click="testNum.x++">点我让x+1</button>

 

在 data 配置项中添加

data: {
  testNum: {
    x: 0
  }
}

在 watch 配置项中添加

// 监视属性
watch: {
  // 监视testNum属性
  testNum: {
    handler(newValue, oldValue) {
      console.log("testNum-------x被改变了")
    }
  },
  // 监视testNum属性中的x属性
  x: {
    handler(newValue, oldValue) {
      console.log("x------x被改变了")
    }
  }
}

浏览器运行结果

可以看到我已经点击四次按钮了,x 的值也已经改变了,按理说应该触发 testNum 或 x 中的 handler 函数,但控制台并没有输出,也就表示这两个中的任何一个 handler 函数都没有被触发。

说说为什么,先来说说上图代码中 watch 配置项中最后一个 x 的配置对象,我就直接说了,这个配置对象根本就不可能被执行,因为 watch 只能监视在 data 中直接定义的属性,而 x 是属于在 testNum 中定义的值,Vue 在 data 中根本找不到 x 这个属性,所以 Vue 就不会管这个配置对象,就更别说触发 handler 函数了。如果想单独监视 testNum 中 x 这个值是否被更改,那就要将配置对象写成这样"testNum.x":{......},更改x值时就可以被监视到了。

 

可以看到点击按钮后触发点击事件,x的值加一并且"testNum.x"中的 handler 函数被触发,控制台输出了相应的内容。

再来说说 watch 中第一个"testNum"的配置对象,我在页面中是让 testNum 里的 x 值进行加一,由于 watch 默认只能监视到属性本身是否发生了变化,那么无论怎么更改 testNum 中 x 的值,testNum 本身都是不会变化的,除非给 testNum 重新赋值一个新的对象,那么此时 Vue 是会监视到 testNum 变化的。对于一个对象来说,如果想在修改其中的值时就能被监视到,那就必须在属性的配置对象中添加 deep 这个配置项,并且要将 deep 的值指定为 true,具体用法和 immediate 一样。修改之后再来看看控制台是否会输出相应的内容。

 在监视属性中添加deep属性

// 监视testNum属性
  testNum: {
    // 深度监视,主要用来监视多层结构的对象或数组
    handler(newValue, oldValue) {
      console.log("testNum-------x被改变了")
    }
  },

在 testNum 属性配置对象中添加 deep 之后,在页面中增加 x 的值,控制台输出相应的内容了,那就说明 testNum 中的 handler 函数被触发了。

监视属性的简写形式

在定义某个监视属性时,如果不需要 immediate、deep 等配置,那就完全可以将监视属性简写成函数式。

watch: {
   // 直接将属性简写成函数,这个函数就是之前的handler函数
   isSunny(newValue, oldValue) {
       console.log("new: ", newValue, "old: ", oldValue)
   }
}

总结

  1. 当被监视的属性发生变化时,回调函数handler会被自动调用并进行相应的操作。

  2. 所要监视的属性必须存在,才能进行监视,否则不会有效果,控制台也不会报错。

  3. 深度监视:

    1. Vue中的watch默认不监测对象内部值的改变。

    2. 配置deep:true就可以检测到对象内部值的改变了

  4. 注意:

    1. 在使用watch监测数据是要根据数据的具体结构,再决定是否使用深度监视。

    2. Vue自身可以监测对象内部值的改变,但由Vue提供的watch默认不行。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到