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>

二、对于对象

<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>

监听对象本身

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

<script>
  export default {
    watch: {
      friend(newVal, oldVal) {
        console.log("friend:newVal--" + newVal + ",oldVal--" + oldVal);
      }
    }
  }
</script>

触发监听

直接改变对象会触发监听

this.friend = {
  friendName: "yin",
  name: "lu",
};

监听对象内属性变化

方法一:深度检测

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

<script>
  export default {
    watch: {
      friend: {
        handler(newVal, oldVal) {
          console.log("deep friend:newVal--" + newVal + ",oldVal--" + oldVal);
        },
        deep: true,
      },
    }
  }
</script>

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

watch : {
    newA : {
        handler : function (newVal, oldVal) {
            console.log(newVal,oldVal)
        },
        immediate : true, //初始化页面后立即监听
        deep: true,
    } 
}  
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>

方法三:使用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、修改现有对象某个属性对应的值

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

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

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

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

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

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

三、对于数组

<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>

监听数组

<script>
  export default {
    watch: {
      colors(newVal, oldVal) {
        console.log("colors:newVal--" + newVal + ",oldVal--" + oldVal);
      },
    },
  }
</script>

触发监听

1、直接赋值新数组

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

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;		//渲染成功 = 触发监听

3、push数组

Vue可以监听

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

4、修改数组的长度

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

  • this.$set(arr, index, newVal);
  • 使用数组 splice 方法可以监听
  • 使用临时变量直接赋值的方式,原理与直接赋值数组一样
this.colors.length = 1;	// 数据修改成功,视图渲染不成功
方法一:
this.colors.splice(1)	// 渲染成功 = 触发监听	1之后数组的元素都被删除,包括1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值