vue2失去响应式


原理

因为vue的definePrototype(访问器属性)原因,无法监听复杂数据类型属性新增删除, 在初始时在data里面的数据会受到监听,但是当页面加载完我们给响应式的对象、数组新增删除属性的时候,新增删除的操作就不是响应式的, 页面也不会变化

<template>
  <div>
    <h2>{{ obj }}</h2>
    <h2>{{ arr }}</h2>
  </div>
</template>
<script>
export default {
  data() {
    return {
      obj: {
        a: "Hello World!",
      },
      arr: [1, 2, 3],
    };
  },
  mounted() {
    this.changeObj();
    this.changeArr();
  },
  methods: {
    changeObj() {
      this.obj.b = "新增的属性b";
      console.log(this.obj);
    },
    changeArr() {
      this.arr[4] = 7;
      this.arr.length = 5;
      console.log(this.arr);
    },
  },
};
</script>

this.set()this.delete解决

this.$set(target, key, value)
this.$delete(target, key)
changeObj() {
     this.$set(this.obj, b, "新增的属性b")
     console.log(this.obj);
 },
 changeArr() {
     this.$set(this.arr, 3, 7)
     console.log(this.arr);
     this.$delete(this.arr, 0)
     console.log(this.arr);
 },

vue3解构赋值原始类型失去响应式


原理

解构赋值原始类型失去响应式
解构赋值引用类型失去响应式
原始类型的赋值相当于按值传递, 引用类型的值就相当于按引用传递

原始类型

// 假设a是个响应式对象
const a={ b:1}
// c 此时就是一个值跟当前的a 已经不沾边了
const c=a.b
 
// 你直接访问c就相当于直接访问这个值 也就绕过了 a 对象的get ,也就像原文中说的失去响应式

引用类型

// 假设a是个响应式对象
const a={ b:{c:3}}
// 当你访问a.b的时候就已经重新初始化响应式了,此时的c就已经是个代理的对象
const c=a.b
 
// 你直接访问c就相当于访问一个响应式对象,所以并不会失去响应式

禁止直接赋值reactive响应式对象

由于解构赋值的问题, 他直接禁止了reactive的解构赋值

// 当reactive 之后返回一个代理对象的地址被vue 存起来,
// 用一个不恰当的比喻来说,就是这个地址具备响应式的能力
const vue = reactive({ a: 1 })
 
//  而当你对于vue重新赋值的时候不是将新的对象赋值给那个地址,而是将vue 换了个新地址
// 而此时新地址不具备响应式,可不就失去响应式了吗
vue = { b: 2 }

通过storeToRefs解构pinia属性保持响应式

import { storeToRefs } from"pinia";

const system = useSystem();
const { isNewProject, isOpenEdit } = storeToRefs(system)
Logo

前往低代码交流专区

更多推荐