• vue视图响应-watch


    数据改变(vue视图上的数据能渲染成功)时会触发对应的监听器watch。

    vue提供了watch方法,用于监听实例内data数据的变化。

    一、普通类型字符串等监听

    直接监听

    <template>
    <div class="about">
      <!-- v-bind只视图绑定数据,视图修改无法触发监听watch方法,只能数据修改触发watch并渲染视图 -->
      <!-- v-model实现双向数据绑定,视图修改触发监听watch方法 -->
      <div>
        <input type="text" :value="name" />
        <button @click="change1">更新视图</button>
      </div>
      <div>
        <input type="text" v-model="age" />
        <button @click="change2">更新视图</button>
      </div>
    </div>
    </template>
    <script>
      export default {
        data() {
          return {
            name: "lilu",
            age: 20,
          };
        },
        methods: {
          change1() {
            this.name = this.name + "1";
          },
          change2() {
            this.age = this.age + "1";
          },
        },
        watch: {
          // 修改字符串、数组直接渲染视图,监听到改变
          name(newVal, oldVal) {
            console.log("name:newVal--" + newVal + ",oldVal--" + oldVal);
          },
          age: function (newVal, oldVal) {
            console.log("age:newVal--" + newVal + ",oldVal--" + oldVal);
          },
        }
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    二、对于对象

    <template>
    <div class="about">
      <input type="text" :value="JSON.stringify(friend)" style="width: 300px" />
      <input type="text" :value="friend.friendName" />
      <button @click="changeFriendName">更新视图</button>
    </div>
    </template>
    <script>
      export default {
        data() {
          return {
            obj: "oo",
            friend: {
              friendName: "yin",
              age: 24,
            },
          };
        },
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    监听对象本身

    直接监听对象是监听对象的指向,不能监听到某个对象里面属性的变化。
    如果需要监听的数据是对象内的某一属性值的变化,直接watch对象friend是检测不到变化的,这是因为friend这个对象的指向并没有发生改变。

    <script>
      export default {
        watch: {
          friend(newVal, oldVal) {
            console.log("friend:newVal--" + newVal + ",oldVal--" + oldVal);
          }
        }
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    触发监听

    直接改变对象会触发监听

    this.friend = {
      friendName: "yin",
      name: "lu",
    };
    
    • 1
    • 2
    • 3
    • 4

    监听对象内属性变化

    方法一:深度检测

    deep设为了true,修改了这个friend中的任何一个属性,都会执行handler这个方法。不过这样会造成更多的性能开销,尤其是对象里面属性过多,结构嵌套过深的时候。而且有时候我们就只想关心这个对象中的某个特定属性。

    <script>
      export default {
        watch: {
          friend: {
            handler(newVal, oldVal) {
              console.log("deep friend:newVal--" + newVal + ",oldVal--" + oldVal);
            },
            deep: true,
          },
        }
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    扩展:handler声明函数或函数表达式都可以,但是不能箭头函数

    watch : {
        newA : {
            handler : function (newVal, oldVal) {
                console.log(newVal,oldVal)
            },
            immediate : true, //初始化页面后立即监听
            deep: true,
        } 
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    immediate属性

    没有的时候上面的例子是值变化时候,watch才执行,我们想让值最初时候watch就执行就用到了handlerimmediate属性,immediate : true代表在wacth里声明了newA这个方法之后立即先去执行handler方法,如果设置了false,那么效果和没有一样

    方法二:字符串来表示属性的调用

    <script>
      export default {
        watch: {
          "friend.friendName"(newVal, oldVal) {
            console.log("string friend:newVal--" + newVal + ",oldVal--" + oldVal);
          },
        }
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方法三:使用computed属性

    <script>
      export default {
        watch: {
          // 和computed计算属性名一样
          friendName(newVal, oldVal) {
            console.log("computed friend:newVal--" + newVal + ",oldVal--" + oldVal);
          },
        },
        computed: {
          friendName() {
            return this.friend.friendName;
          },
        },
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    触发监听

    1、修改现有对象某个属性对应的值

    把对象某个属性的值修改都触发,无论改成基本类型还是引用对象,而且引用对象内vue也能监听到。

    // 例1:数据修改成功,视图修改成功=三种方式的属性监听都触发
    this.friend.friendName = "li";
    
    • 1
    • 2
    2、属性的添加

    对于已经创建的实例,Vue 不允许动态添加根级别(外层内层都监听不到)的响应式 property: 无法渲染
    解决方案:

    • 预先留出变量
    • 使用this.$set / Vue.set()
    this.friend.sex = "girl";		// 数据修改但无法渲染 = 监听不到
    this.$set(this.friend, "sex", "boy"); // 可以渲染,deep watch可以监听
    
    • 1
    • 2
    3、属性的删除

    Vue 无法检测 property 的移除
    解决方案:

    • Vue.delete()删除对象某个元素后,会立即触发页面渲染:Vue.delete(propertyName/index)
    delete this.friend.age;	//数据删除但无法渲染 = 监听不到
    this.$delete(this.friend, "age"); // 可以渲染,deep watch可以监听
    
    • 1
    • 2

    三、对于数组

    <template>
    <div class="about">
      <input type="text" :value="colors" />
      <input type="text" :value="colors[0]" />
      <button @click="changeColors">更新视图</button>
    </div>
    </template>
    <script>
      export default {
        data() {
          return {
            colors: ["red", "orange", "green"]
          };
        },
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    监听数组

    <script>
      export default {
        watch: {
          colors(newVal, oldVal) {
            console.log("colors:newVal--" + newVal + ",oldVal--" + oldVal);
          },
        },
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    触发监听

    1、直接赋值新数组

    // 例子1:修改成功,数组、元素都渲染成功,触发上面对数组的监听
    this.colors = ["1", "2", "3"];
    
    • 1
    • 2

    2、利用索引直接设置一个数组项

    例如:arr[indexOfItem] = newValue;
    解决方案:

    • 使用this.$set(arr, index, newVal)
    • 使用splice(indexOfItem, 1, newValue):
    • 使用临时变量直接赋值的方式,原理与直接赋值数组一样
    this.colors[0] = "blue";  // 不是响应的,数据修改成功但渲染不成功 = 不触发监听
    // 方法一:
    this.$set(this.colors, 0, "blue")		// 渲染成功 = 触发监听
    // 方法二
    this.colors.splice(0, 1, "blue");	// 渲染成功 = 触发监听
    // 方法三
    let temp = [...this.colors];
    temp[0] = "blue";
    this.colors = temp;		//渲染成功 = 触发监听
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、push数组

    Vue可以监听

    this.colors.push('yellow')	// 数据添加成功,视图渲染成功
    
    • 1

    4、修改数组的长度

    例如:arr.length = newLength
    长度大于原数组就将后续元素设置为 undefined, 长度小于原数组就将多余元素截掉。
    解决方案:

    • this.$set(arr, index, newVal);
    • 使用数组 splice 方法可以监听
    • 使用临时变量直接赋值的方式,原理与直接赋值数组一样
    this.colors.length = 1;	// 数据修改成功,视图渲染不成功
    方法一:
    this.colors.splice(1)	// 渲染成功 = 触发监听	1之后数组的元素都被删除,包括1
    
    • 1
    • 2
    • 3
  • 相关阅读:
    ABP - 本地事件总线
    性能测试常见故障和解决思路
    VSCode安装使用教程
    深入理解Java虚拟机读书笔记--10Java内存模型
    SPSS安装激活教程(包含网盘链接)
    django DRF增删改查查
    解决selenium访问网页中多个iframe,导致无法锁定元素的问题
    通信世界扫盲基础二(原理部分)
    Java项目(三)-- SSM开发社交网站(1)--SSM整合之Spring与Spring MVC环境配置
    【数据结构篇】线性表2 —— 栈和队列
  • 原文地址:https://blog.csdn.net/Vanessa_Li/article/details/127631681