vue 【v3和v2响应式原理差异及优劣】


一、vue2响应式原理

vue2的响应式是通过Object.definProperty方法,对data中的属性进行递归处理,为每一个属性加入getter和setter方法,在getter中注入依赖收集的逻辑,在setter中定义发布者逻辑,每次属性改变时,通知所有在getter中收集的依赖项进行更新

const target = {
	name:"default name"
}
let name=target.name

const handler = {
	get(){
		// 订阅者逻辑
		return name;
	},
	set(newVal){
		// 发布者逻辑
		name=newVal;
	}
}
Object.defineProperty(target,handler);

// vue 模板
<template>
	// 触发订阅者逻辑,收集div依赖
	<div v-text="name"></div>
</tamplate>

// vue javascript
this.name="update"; //触发搜集者逻辑

Object.defineProperty更多使用方法


二、vue3响应式原理

vue3使用的式es6的Proxy 对象,它仍然遵循发布者和订阅者的设计模式,在组件或者式html元素使用响应式对象时,将其收集为依赖。等到响应式对象发生改变时通知所有的依赖项进行更新

Proxy 对象

  const obj = {
    name: "default name",
  };
  const handle = {
    get(obj, field) {
      console.log("get", obj, field);
      return obj[field];
    },
    set(obj, field, value) {
      console.log("get", obj, field);
      obj[field] = value;
    },
    deleteProperty(obj, field) {
      delete obj[field];
      console.log("del", obj, field);
    },
  };
  const proxy1 = new Proxy(obj, handle);
  console.log("读取", proxy1.filed);
  proxy1.name = "updated name";
  delete proxy1.name;
  console.log("源数据", obj);

proxy对象和源对象obj是相互独立的两个对象,proxy只做拦截作用 在你未定义set时,他会自动做一个分发代理,即

const obj = {
	name:"default name"
}
const handler = {}
const proxy1 = new Proxy(obj,handler)
proxy1.name="updated name";
console.log(obj.name); // updated name

定义handler.set之后,你需要手动去改变obj的值,即

const obj = {
	name:"default name"
}
const handler = {
	set(target,prop,value){
		target[prop] = value; // 需要手动修改obj的值
	}
}

Proxy更多使用方法


三、对比vue2,vue3响应式的优势

vue2数组中新增属性不会有响应式

data(){
	return {
		list:[1,2],
		objList:[{name:1}]
	}
}


this.list[1]='9'; // 基本类型数组,改变原有的元素不会触发视图更新
this.objList[0].name="update";// 引用类型数,改变原有元素属性,触发更新
this.objList[1]={name:2}; // 引用类型数组,新增元素不会触发更新

vue2对象属性的新增、删除无法监听

data(){
  return {
    obj:{name:"name"}
  }
}

delete this.obj.name; // 不触发视图更新
this.obj.age="age"; // 不触发视图更新

在vue2中要使属性变成响应式只能是放在data或者调用$set

data(){
  return {
    name:'name',
    list:[]
  }
}

this.$set(this.list,0,1)

vue2 无法处理map、set中属性改变的响应式

data(){
  return {
    map:new Map([['key0','val1']])
    set:new Set(['value1','value2'])
  }
}

this.map.set('key1','val1'); // 不触发更新
this.map.delete('key1');// 不触发更新
this.set.add('value0');// 不触发更新
this.set.delete('value0');// 不触发更新

需要递归data属性,如果data对象层级复杂,将会比较消耗性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极简风格

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值