手写Vue3响应式数据原理

这篇具有很好参考价值的文章主要介绍了手写Vue3响应式数据原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

我们想要对一个对象数据进行处理,从而实现更改dom。但如何更改对一个对象数据进行更改呢?

vue2 的双向数据绑定是利⽤ES5 的⼀个 API ,Object.defineProperty()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。

vue3 中使⽤了 ES6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy 监听属性的变化,从⽽ 实现对数据的监控。

这⾥是相⽐于vue2版本,使⽤proxy的优势如下:

    1. defineProperty只能监听某个属性,不能对全对象监听可以省去for…in…、闭包等内容来提升效率(直接绑定整个对象即可)
    1. 监听数组,不⽤再去单独的对数组做特异性操作,通过Proxy可以直接拦截所有对象类型数据的操作,完美⽀持对数组的监听。

我们想要知道如何实现Vue3响应式数据,就要知道proxy这个概念。


一、proxy是什么?

Proxy(代理)是一种计算机网络技术,其作用是充当客户端和服务器之间的中间人,转发网络请求和响应。当客户端发送请求时,代理服务器会接收并转发请求到目标服务器,然后将服务器返回的响应转发给客户端。

相当于明星和经纪人,想要找明星办事,需要找他的经纪人,明星的事都交给经纪人做。明星就是源对象,经纪人就相当于proxy。

proxy用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

1.1 proxy基本使用

// 定义一个源对象
let obj = {
	name: 'qx',
	age: 24
}
// 实现一个Proxy,传入要代理的对象和get和set方法
const proxy =  new Proxy(obj, {
	// get中返回代理对象的,target代表源对象(也是上面的obj),key代表obj中每个属性
	get(target, key) {
		return target[key];
	},
	// set中返回代理对象的,target代表源对象(也是上面的obj),key代表obj中每个属性,value是修改的新值
	set(target, key, value) {
		target[key] = value
		return true
	}
})
console.log(proxy)

obj.name = 'xqx'
// 现在打印的是修改后的proxy,看看会变成什么样?  已经修改好了
console.log(proxy)

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

二、实现最基本的reactive函数

reactive 用于创建一个响应式对象,该对象可以包含多个属性和嵌套属性。当使用 reactive 创建响应式对象时,返回的对象是一个代理对象,该对象具有与原始对象相同的属性,并且任何对代理对象属性的更改都将触发组件的重新渲染。

既然我们已经知道reactive是个函数,并且返回的是一个代理对象,先把最基本的框架搭出来

function reactive(data) {
	return new Proxy(data, {
		get(target, key) {
			return target[key];
		},
		set(target, key, value) {
			target[key] = value
			return true
		}
	})
}

看似已经完成了,但是当传入非对象时,却报错

提示这个对象是对象类型的,例如数组之类的,并只是{}这个。

const arr = true;
console.log(reactive(arr))

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端
提示proxy要传入一个对象,所以需要先判断是不是对象

function reactive(data) {
	//判断是不是对象,null也是object要排除
	if(typeof data === Object && data !== null) return 
	
	return new Proxy(data, {
		get(target, key) {
			return target[key];
		},
		set(target, key, value) {
			target[key] = value
			return true
		}
	})
}

三、实现基本响应式系统

我们知道处理数据就是为了让视图更新,但一个系统离不开副作用函数。

副作用函数,顾名思义,会产生副作用的函数被称为副作用函数。通俗来说,就是这个函数可以影响其他的变量。

来看最基本的副作用函数

<div id="app"></div>
<script>
	let obj = {
		name: 'qx'
	}
	function effect(){
		app.innerText = obj.name
	}
	
	effect()
</script>

现在我们需要通过前面reactive函数来完善一个基本的响应式系统

<body>
	<div id="app"></div>
	<script>
		let obj = {
			name: 'qx',
			age: 24
		}
		function reactive(data) {
			if(typeof data === Object && data !== null) return 
			return new Proxy(data, {
				get(target, key) {
					return target[key];
				},
				set(target, key, value) {
					target[key] = value
					return true
				}
			})
		}
		const state = reactive({name:'xqx'});
		
		function effect(){
			app.innerText = state.name
		}
		
		effect()
	</script>
</body>

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端
到现在一个最基本的响应式系统出现

四、完善基本响应式系统

如果多个副作用函数同时引用一个变量,我们需要当变量改变时,每一个副作用函数都要执行。

4.1 执行每一个副作用函数

可以把多个副作用函数放在一个列表里,在每次对对象操作时,执行proxy中的set方法时,对每一个副作用函数进行遍历。

<body>
	<div id="app"></div>
	<script>
		let obj = {name: 'qx'}
		let effectBucket = [];
		
		function reactive(data) {
			if(typeof data === Object && data !== null) return 
			return new Proxy(data, {
				get(target, key) {
					return target[key];
				},
				set(target, key, value) {
					target[key] = value
					effectBucket.forEach(fn=>fn())
					return true
				}
			})
		}
		
		const state = reactive({name:'xqx'});
		
		function effect(){
			app.innerText = state.name
			console.log('副作用函数1被执行')
		}
		effectBucket.push(effect)
		
		function effect1(){
			app.innerText = state.name
			console.log('副作用函数2被执行')
		}
		effectBucket.push(effect1)
		
		state.name = 'zs'
	</script>
</body>

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

但是我们要是传两个同样的副作用函数怎么办。

function effect(){
	app.innerText = state.name
	console.log('副作用函数1被执行')
}
effectBucket.push(effect)
effectBucket.push(effect)

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端
发现列表里有两个重复的effect函数,如果列表很长,foreach也会浪费时间,那么大大浪费性能。es6有个Set数据结构可以帮助我们解决这个问题。

let effectBucket = new Set();

const state = reactive({name:'xqx'});

function effect(){
	app.innerText = state.name
	console.log('副作用函数1被执行')
}
effectBucket.add(effect)  //添加两次
effectBucket.add(effect)

function effect1(){
	app.innerText = state.name
	console.log('副作用函数2被执行')
}
effectBucket.add(effect1)

console.log(effectBucket)

我们把effect添加两次,看看结果是什么样的
手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

4.2 实现依赖收集

前面我们只是对一个对象中的属性进行处理,如果多个属性都要更改呢?我们以上的操作会让每一个副作用函数都执行。

假设我们有这样一个结构

let obj = {name: 'qx',age:24}

我想改name属性时,只更新有name的副作用函数,不必把列表里所有副作用函数都更新。这就需要依赖收集。

4.2.1 基本实现

对每一个副作用函数进行一个保存,当调用副作用函数时,会执行proxy中的get方法,在get方法把当前副作用函数添加列表,就实现了当前依赖属性和副作用函数关联在一起。

具体实现步骤如下:

let obj = {name: 'qx',age:24}
let effectBucket = new Set();

let activeEffect = null;   //1.保存当前的副作用函数状态

function reactive(data) {
	if(typeof data === Object && data !== null) return 
	return new Proxy(data, {
		get(target, key) {
			if(activeEffect != null){              //4. 将当前保存的副作用函数添加到副作用函数列表中
				effectBucket.add(activeEffect)  
			}
			return target[key];
		},
		set(target, key, value) {
			target[key] = value
			effectBucket.forEach(fn=>fn())
			return true
		}
	})
}
const state = reactive(obj);
function effectName(){
	console.log('副作用函数1被执行',state.name)
}
activeEffect = effectName()  // 2.将当前副作用函数赋值给activeEffect 
effectName()                 // 3.调用副作用函数,相当于访问proxy的get方法
activeEffect = null;         // 5.将副作用函数状态置空,给下一个副作用函数用

function effectAge(){
 	console.log('副作用函数2被执行',state.age)
}
activeEffect = effectAge()
effectAge()
activeEffect = null;

state.name = 'zs'

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端
再简化一下,对上面重复代码进行一个封装。调用的时候直接调封装后的方法

function registEffect(fn) {
	if (typeof fn !== 'function') return;
	activeEffect = fn();
	fn();
	activeEffect = null;
}

4.3 改进桶结构

Set结构像数组,只是能做到去重,并不能实现不同属性对应不同集合。需要我们改进成一个属性对应多个集合。

另一个数据结构Map出现在面前,它是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

创建一个这样的结构。

let a = {
	name: Set(fn,fn),
	age:Set(fn,fn)
}

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

let effectBucket = new Map();  //{name:Set(fn,fn),age:Set(fn,fn)}
let activeEffect = null;

function reactive(data) {
	if (typeof data === Object && data !== null) return
	return new Proxy(data, {
		get(target, key) {
			if (activeEffect !== null) {
				let deptSet;
				if(!effectBucket.get(key)){                       //没有得到key,说明没有添加过
					deptSet = new Set();            //重新创建一个集合
					effectBucket.set(key,deptSet);  //每次添加一个属性{name:Set(fn,fn)}结构
				}
				deptSet.add(activeEffect)
			}
			return target[key];
		},
		set(target, key, value) {
			target[key] = value
			//从副作用桶中依次取出每一个副作用函数执行
			let deptSet = effectBucket.get(key);
			if(deptSet){                   
				deptSet.forEach(fn => fn())
			}
			return true
		}
	})
}

继续封装收集依赖
get

function track(target, key) {
	if (!activeEffect) return
	let deptSet;
	if (!effectBucket.get(key)) { //没有得到key,说明没有添加过
		deptSet = new Set(); //重新创建一个集合
		effectBucket.set(key, deptSet);
	}
	deptSet.add(activeEffect)
}

set

function trigger(target, key) {
	let deptSet = effectBucket.get(key);
	if (deptSet) {
		deptSet.forEach((fn) => fn())
	}
}

手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

function track(target, key) {
	if (!activeEffect) return
	let deptMap =effectBucket.get(key);
	if (!deptMap) { //没有得到key,说明没有添加过
		deptMap = new Map(); //重新创建一个集合
		effectBucket.set(target, deptMap);
	}
	let depSet = deptMap.get(key)
	if(!depSet){
		depSet = new Set()
		deptMap.set(key,depSet)
	}
	deptSet.add(activeEffect)
}

function trigger(target, key) {
	let depMap = effectBucket.get(target)
	if(!depMap) return
	let deptSet = effectBucket.get(key);
	if (deptSet) {
		deptSet.forEach((fn) => fn())
	}
}

五、相关面试题

1.Object.defineProperty 和 Proxy 的区别?

  1. Proxy 可以直接监听对象而非属性;
  2. Proxy 可以直接监听数组的变化;
  3. Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等 是 Object.defineProperty 不具备的;
  4. Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty 只能遍历对象属性直接修改
  5. Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准 的性能红利
  6. Object.defineProperty 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题, 而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重 写

2.vue2.0 和 vue3.0 有什么区别? 双向绑定更新?

vue2 的双向数据绑定是利⽤ES5 的⼀个 API ,Object.defineProperty()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。

vue3 中使⽤了 ES6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy 监听属性的变化,从⽽ 实现对数据的监控。

这⾥是相⽐于vue2版本,使⽤proxy的优势如下:

  1. defineProperty只能监听某个属性,不能对全对象监听 可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)

  2. 监听数组,不⽤再去单独的对数组做特异性操作,通过Proxy可以直接拦截所有对象类型数据的操作,完美⽀持对数组的监听。

获取props

vue2在script代码块可以直接获取props,vue3通过setup指令传递

API不同

Vue2使⽤的是选项类型API(Options API),Vue3使⽤的是合成型API(Composition API)

建立数据data

vue2是把数据放入data中,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造得时候触发。

生命周期不同

vue2 vue3
beforeCreate setup() 开始创建组件之前,创建的是data和method
created setup()
beforeMount onBeforeMount 组件挂载到节点上之前执行的函数
mounted onMounted 组件挂载完成后执行的函数
beforeUpdate onBeforeUpdate 组件更新之前执行的函数
updated onUpdated 组件更新完成之后执行的函数
beforeDestroy onBeforeUnmount 组件挂载到节点上之前执行的函数
destroyed onUnmounted 组件卸载之前执行的函数
activated onActivated 组件卸载完成后执行的函数
deactivated onDeactivated

关于v-if和v-for的优先级:

vue2 在一个元素上同时使用 v-if 和 v-for v-for会优先执行

vue3 v-if 总会优先于 v-for生效

vue2和vue3的diff算法

vue2

vue2 diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点 不同的地方,最后用patch记录的消息去局部更新Dom。

vue2 diff算法会比较每一个vnode,而对于一些不参与更新的元素,进行比较是有 点消耗性能的。

vue3

vue3 diff算法在初始化的时候会给每个虚拟节点添加一个patchFlags,patchFlags 就是优化的标识。

只会比较patchFlags发生变化的vnode,进行更新视图,对于没有变化的元素做静 态标记,在渲染的时候直接复用。

3.Vue 是如何实现数据双向绑定的?

Vue 数据双向绑定主要是指:数据变化更新视图

  • 输入框内容变化时,Data 中的数据同步变化。即 View => Data 的变化。
  • Data 中的数据变化时,文本节点的内容同步变化。即 Data => View 的变化

Vue 主要通过以下 4 个步骤来实现数据双向绑定的:

  • 第一步:需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。

  • 第二步:compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。

  • 第三步:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:

    • 1、在自身实例化时往属性订阅器(dep)里面添加自己
    • 2、自身必须有一个 update()方法
    • 3、待属性变动 dep.notice()通知时,能调用自身的 update()方法,并触发 Compile中绑定的回调,则功成身退。
  • 第四步:MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。

4.介绍下 Set、Map、WeakSet 和 WeakMap的区别?

Set
Set是一种叫做集合的数据结构,是由一堆无序的、相关联的,且不重复的内存结构组成的组合。集合是以[值,值]的形式存储元素

  1. 成员不能重复;
  2. 只有键值,没有键名,有点类似数组;
  3. 可以遍历,方法有 add、delete、has、clear

WeakSet

  1. WeackSet只能成员只能是引用类型,而不能是其他类型的值;
  2. 成员都是弱引用,随时可以消失(不计入垃圾回收机制)。可以用来保存 DOM 节点,不容易造成内存泄露;
  3. 不能遍历,没有size属性,方法有 add、delete、has ;

Map
Map是一种叫做字典的数据结构,每个元素有一个称作key 的域,不同元素的key 各不相同。字典是以[键,值]的形式存储。

  1. 本质上是键值对的集合,类似集合。Map的键可以时任何类型数据,就连函数都可以。;
  2. 可以遍历,方法很多,可以跟各种数据格式转换;
  3. Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键;

WeakMap

  1. 只接收对象为键名(null 除外),不接受其他类型的值作为键名;
  2. 键名指向的对象,不计入垃圾回收机制;
  3. 不能遍历,没有clear清空方法,方法同 get、set、has、delete ;

5.Vue2.0为什么不能检查数组的变化?该怎么解决?

  • 无法检测数组/对象的新增?

Vue检测数据的变动是通过Object.defineProperty实现的,所以无法监听数组的添加操作是可以理解的,因为是在构造函数中就已经为所有属性做了这个检测绑定操作。

  • 无法检测通过索引改变数组的操作?即vm.items[indexOfItem] = newValue?
function defineReactive(data, key, value) {
	Object.defineProperty(data, key, {
		enumerable: true,
		configurable: true,
		get: function defineGet() {
			console.log(`get key: ${key} value: ${value}`)
			return value
		},
		set: function defineSet(newVal) {
			console.log(`set key: ${key} value: ${newVal}`)
			value = newVal
		}
	})
}

function observe(data) {
	Object.keys(data).forEach(function(key) {
		console.log(data, key, data[key])
		defineReactive(data, key, data[key])
	})
}

let arr = [1, 2, 3]
observe(arr)

原来的Object.defineProperty发现通过索引是可以赋值的,并且也触发了set方法,但是Vue为什么不行呢?
手写Vue3响应式数据原理,Vue,javascript,vue.js,前端

对于对象而言,每一次的数据变更都会对对象的属性进行一次枚举,一般对象本身的属性数量有限,所以对于遍历枚举等方式产生的性能损耗可以忽略不计,但是对于数组而言呢?数组包含的元素量是可能达到成千上万,假设对于每一次数组元素的更新都触发了枚举/遍历,其带来的性能损耗将与获得的用户体验不成正比,故vue无法检测数组的变动。文章来源地址https://www.toymoban.com/news/detail-676885.html

解决方案

  • 数组
  1. this.$set(array, index, data)
//这是个深度的修改,某些情况下可能导致你不希望的结果,因此最好还是慎用
this.dataArr = this.originArr
this.$set(this.dataArr, 0, {data: '修改第一个元素'})
console.log(this.dataArr)        
console.log(this.originArr)  //同样的 源数组也会被修改 在某些情况下会导致你不希望的结果 
  1. splice
//因为splice会被监听有响应式,而splice又可以做到增删改。
  1. 利用临时变量进行中转
let tempArr = [...this.targetArr]
tempArr[0] = {data: 'test'}
this.targetArr = tempArr
  • 对象
  1. this.$set(obj, key ,value) - 可实现增、改
  2. watch时添加deep:true深度监听,只能监听到属性值的变化,新增、删除属性无法监听
this.$watch('blog', this.getCatalog, {
    deep: true
    // immediate: true // 是否第一次触发
  });
  1. watch时直接监听某个key
watch: {
  'obj.name'(curVal, oldVal) {
    // TODO
  }
}

到了这里,关于手写Vue3响应式数据原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【vue3源码系列#01】vue3响应式原理(Proxy)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 在学习 Vue3 是如何进行对象的响应式代理之前,我想我们应该先去了解下 ES6 新增的API Proxy 与 Reflect ,可参考【Vue3响应式入门#02】Proxy and Reflect 。之

    2024年02月05日
    浏览(51)
  • Vue3响应式原理 私

    响应式的本质:当数据变化后会自动执行某个函数映射到组件,自动触发组件的重新渲染。 响应式的实现方式就是劫持数据,Vue3的reactive就是通过Proxy劫持数据,由于劫持的是整个对象,所以可以检测到任何对象的修改,弥补了2.0的不足。 名词解释: **副作用函数:**函数的

    2024年02月10日
    浏览(39)
  • 前端Vue篇之Vue3响应式:Ref和Reactive

    在Vue3中,响应式编程是非常重要的概念,其中 Ref 和 Reactive 是两个关键的API。 Ref : Ref 用于创建一个响应式的基本数据类型,比如数字、字符串等。它将普通的数据变成响应式数据,可以监听数据的变化。使用 Ref 时,我们可以通过 .value 来访问和修改数据的值。 Reactive :

    2024年04月25日
    浏览(49)
  • 【Vue3响应式原理#01】Reactivity

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第一节,课程链接在此:Vue 3 Reactivity - Vue 3 Reactivity | Vue Mastery,本文档可作为课程的辅助材料,

    2024年02月08日
    浏览(39)
  • Vue3.0中的响应式原理

    实现原理: - 对象类型:通过 ``Object.defineProperty()``对属性的读取、修改进行拦截(数据劫持)。 - 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。 存在问题: - 新增属性、删除属性, 界面不会更新。 - 直接通过下标修改数组, 界面

    2023年04月17日
    浏览(49)
  • Vue2和Vue3响应式原理实现的核心

    Vue.js 是一个开源的渐进式 JavaScript 前端框架,主要用于构建用户界面和单页应用程序(SPA)。Vue.js 可以轻松地与其他库或现有项目集成使用,并被认为是开发响应式数据驱动的现代 Web 应用的一种有效方式。 Vue.js 的核心特点: 响应式数据绑定:Vue.js 可以通过对数据进行双

    2024年02月08日
    浏览(43)
  • 【源码系列#02】Vue3响应式原理(Effect)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 Vue3中响应数据核心是 reactive , reactive 的实现是由 proxy 加 effect 组合 ,上一章节我们利用 proxy 实现了一个简易版的 reactive,# 【源码系列#01】Vue3响应

    2024年02月05日
    浏览(42)
  • 【源码系列#01】vue3响应式原理(Proxy)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 在学习 Vue3 是如何进行对象的响应式代理之前,我想我们应该先去了解下 ES6 新增的API Proxy 与 Reflect ,可参考【Vue3响应式入门#02】Proxy and Reflect 。之

    2024年02月05日
    浏览(50)
  • 【源码系列#05】Vue3响应式原理(Ref)

    ref: 接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value 可以将 ref 看成 reactive 的一个变形版本,这是由于 reactive 内部采用 Proxy 来实现,而 Proxy 只接受对象作为入参,这才有了 ref 来解决值类型的数据响应, 如果传入 ref 的

    2024年02月03日
    浏览(33)
  • vue2、vue3、react响应式原理、组件声明周期阐述与对比

    响应式原理: Vue.js 的响应式原理是通过使用 Object.defineProperty 函数来实现的。在 Vue.js 中,当一个对象被传入 Vue 实例的 data 选项中时,Vue.js 会将这个对象的属性转换为 getter 和 setter,以便在属性被访问或修改时能够触发相应的更新。 具体来说,Vue.js 会在实例化过程中递归

    2024年02月06日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包