简单的了解一哈 Vue3和Vue2的响应式原理🪶?【vue3:proxy | vue2:Object.defineProperty()】🎈🎈🎈

vue的新项目开发者经常遇到响应式问题,那么vue2和vue3的响应式原理实现流程和主要的区别是 如何~~~ vue3 ——— proxy ♦️ vue2 ———— Object.defineProperty() ?

1. vue2.x的响应式原理

实现原理:通过Object.defineProperty()对属性的读取,修改进行拦截。(也叫数据劫持)即对数据的操作进行监听

   let data = {
        name: "张三",
        age: 30
    }
    let p = {} 
    Object.defineProperty(p, 'name', {    
        get() {
            console.log('访问了name属性');
            return data.name
        },
        set(val) {
            console.log('设置name属性');
            data.name = val
        }
    })
 
//如上存在2个问题:
// 无法添加和删除属性
// 无法捕获到修改数组下标改变对应数组
 
 

 如上存在2个问题:
无法添加和删除属性
无法捕获到修改数组下标改变对应数组

1.1 vue2.x存在的问题
  • 对象数据新增属性和删除属性,界面不会响应更新~~看看下面的列子:

<template>
  <div id="app">
    <p>{{ person.name }}</p>
    <p>{{ person.age }}</p>
    <p v-if="person.sex">{{ person.sex }}</p>
    <button @click="addSex">添加属性</button>
    <button @click="deleteAge">删除属性</button>
  </div>
</template>
<script>
import Vue from "vue";
export default {
  name: "App",
  data() {
    return {
      person: {
        name: "张三",
        age: 20,
      },
    };
  },
  components: {},
  methods: {
    addSex() {
      // this.person.sex = "男";
      // console.log(this.person); // 数据被修改,但是vue监测不到
      // this.$set(this.person, "sex", "男"); // 修改为第一种方式,vue可以检测到
      Vue.set(this.person, "sex", "男"); // 修改为第二种方式,vue也可以检测到
      console.log(this.person);
    },
    deleteAge() {
      // delete this.person.age;  // age被删除改,但是vue监测不到
      this.$delete(this.person, "age");  // 修改为第一种方式,vue可以检测到
      Vue.delete(this.person, "age"); // 修改为第二种方式,vue可以检测到
      console.log(this.person);
    },
  },
};
</script>

 addSex():

this.person.sex = "男";

console.log(this.person); // 数据被修改,但是vue监测不

 this.$set(this.person, "sex", "男"); // 修改为第一种方式,vue可以检测到
 Vue.set(this.person, "sex", "男"); // 修改为第二种方式,vue也可以检测到
 console.log(this.person);

deleteAge()

 delete this.person.age;  // age被删除改,但是vue监测不到
 this.$delete(this.person, "age");  // 修改为第一种方式,vue可以检测到
 Vue.delete(this.person, "age"); // 修改为第二种方式,vue可以检测到
  console.log(this.person);

 

  • 数组数据直接通过修改下标,界面不会响应更新

 <div id="app">
    <p v-for="(item, index) in nameArr" :key="index">{{ item }}</p>
    <button @click="update">添加属性</button>
  </div>
<script>
import Vue from "vue";
export default {
  name: "App",
  data() {
    return {
      nameArr: ["刘备", "关羽"],
    };
  },
  methods: {
    update() {
      // this.nameArr[0] = "张飞"; // 数据被修改了,但是vue 检测不到
      // this.nameArr.splice(0, 1, "张飞"); // 修改为第一种方式,数据可以被检测到
      // this.$set(this.nameArr, 0, "张飞"); // 修改为第二种方式,数据可以被检测到
      Vue.set(this.nameArr, 0, "张飞"); // 修改为第三种方式,数据可以被检测到
      console.log(this.nameArr);
    },
  },
};
</script>

update() 
      this.nameArr[0] = "张飞"; // 数据被修改了,但是vue 检测不到
      this.nameArr.splice(0, 1, "张飞"); // 修改为第一种方式,数据可以被检测到
      this.$set(this.nameArr, 0, "张飞"); // 修改为第二种方式,数据可以被检测到
      Vue.set(this.nameArr, 0, "张飞"); // 修改为第三种方式,数据可以被检测到
      console.log(this.nameArr);

2、vue3响应式原理

首先看一下vue3是否还存在vue2.x 中的问题:  ~~~对象数据新增属性和删除属性,不存在vue2.x 中的问题了。

<template>
  <div>
    <p>{{ person.name }}</p>
    <p>{{ person.age }}</p>
    <p>{{ person.sex }}</p>
    <button @click="addSex">添加属性</button>
    <button @click="deleteSex">删除属性</button>
  </div>
</template>
 
<script>
import { reactive } from "vue";
export default {
  name: "App",
  components: {},
  setup() {
    let person = reactive({
      name: "张三",
      age: 20,
    });
    console.log(person);
    //定义添加属性
    function addSex() {
      person.sex = "男";
      console.log(person);
    }
    // 定义删除属性
    function deleteSex() {
      delete person.sex;
      console.log(person);
    }
    return {
      person,
      addSex,
      deleteSex,
    };
  },
};
</script>
  • 数组数据直接通过修改下标,修改数组,不存在vue2.x 中的问题了💦💦💦

<template>
  <div>
    <p v-for="(item, index) in person.like" :key="index">{{ item }}</p>
    <button @click="change">修改数组的值</button>
  </div>
</template>
 
<script>
import { reactive } from "vue";
export default {
  name: "App",
  components: {},
  setup() {
    let person = reactive({  
      name: "张三",
      age: 20,
      like: ["打球", "敲代码"],
    });
    console.log(person); // proxy 实例对象
    function change() {
      person.like[0] = "打台球";
    }
    return {
      person,
      change,
    };
  },
};
</script>
 
  • 数组数据直接通过修改下标,修改数组,不存在vue2.x 中的问题了💦💦💦
2.1 vue3响应式原理

首先说一下Reflect的作用。

// Reflect是window下的一个内置对象
// 1. 使用reflect 访问数据
    let obj = {
        name: '张三',
        age: 20
    }
    console.log(Reflect.get(obj, 'name')); // 张三
// 2.使用Reflect 修改数据
    Reflect.set(obj, 'age', 50)
    console.log(obj);
 
//3.使用Reflect删除数据
 Reflect.deleteProperty(obj, 'name') 
    console.log(obj);

vue3响应原理代码

通过Proxy代理,拦截对象中任意属性的变化,包括属性的读取,修改、设置、删除。

通过Reflect 反射对被代理对象的属性进行操作。

    let data = {
        name: "张三",
        age: 30
    }
    console.log(Proxy);
    // 使用p 对象代理data, Proxy为window 下的内置代理函数
    let p = new Proxy(data, {
        // 读取属性
        get(target, propName) {
            // target 就是 data
            console.log(`读取p上个${propName}属性`);
            return Reflect.get(target, propName)
        },
        // 修改和设置属性
        set(target, propName, value) {
            // value 为赋的值
            console.log(`修改p的${propName}属性`);
            // target[propName] = value
            Reflect.set(target, propName, value)
 
        },
        //删除属性
        deleteProperty(target, propName) {
            console.log(`删除p上的${propName}属性`);
            // return delete target[propName]
            return Reflect.deleteProperty(target, propName)
        }
    })

Vue3 的响应式系统通过 Proxy 实现了更强大、更高效的反应机制,解决了 Vue2 中的多个痛点,就是属性增删改查的时候页面监听不到数据的更新。对于现代浏览器项目,Vue3 的响应式系统是更优的选择

 

posted @ 2025-04-27 16:40  Mahmud(مەھمۇد)  阅读(18)  评论(0)    收藏  举报