vue.js响应式原理,vue如何实现响应式
本文主要详细介绍了实现vue的数据响应原理。通过示例代码详细介绍,对大家的学习或工作有一定的参考价值。有需要的朋友下面和边肖一起学习。
本文主要针对不知道或者没有接触过vue响应式源代码的朋友。其主要目的是对vue的响应式原理有一个基本的了解。如果你在面试中被问到这样的问题,你能知道面试官想让你回答什么吗?「PS:如文中有错误,欢迎朋友们指正」
响应式的理解
响应,顾名思义,就是数据更改,这将导致视图更新。本文主要分析vue2.0中对象和数组响应原理的实现,我们将在下一篇文章中根据收集和视图更新进行分析。
在vue中,我们所说的响应式数据一般是指数组类型和对象类型的数据。Vue内部通过Object.defineProperty方法劫持对象的属性,而数组是通过重写数组实现的。下面简单实现一下吧。
首先,我们定义一个需要拦截的数据。
const vm=new Vue({
data () {
返回{
计数:0,
人:{姓名: xxx },
arr: [1,2,3]
}
}
})
let数组方法
Function Vue (options) {//这里只考虑对数据的操作。
let data=options.data
if(数据){
数据=这个。_data=typeof data===function ?data.call(this) : data
}
观察者(数据)
}
函数观察者(数据){
if(数据类型!==object data===null) {
返回数据
}
如果(数据。__ob__) {//有__ob__属性,表示已经被拦截。
返回数据
}
新观察家(数据)
}
arrayMethods、Observer和__ob__的实现和作用这里请继续往下看。
实现 Observer 类
课堂观察者{
构造函数(数据){
对象。Define Property (data, __ob__ ,{//在数据上定义_ _ ob _ _属性,数组劫持时需要用到。
Enumerable: false,//不可枚举
可配置:false,//不可配置
值:这个//值是一个观察者实例。
})
If (Array.isArray(data)) {//截取数组
数据。__proto__=arrayMethods //原型继承
this.observerArray(数据)
} else {//要拦截的对象
this.walk(数据)
}
}
行走(数据){
const keys=Object.keys(data)
for(设I=0;i keys.lengthi ) {
const key=keys[i]
defineReactive(data,key,data[key])
}
}
ObserverArray (data) {//截取数组中的每一项
data.forEach(值=观察者(值))
}
}
对象的拦截
劫持物件要注意几点:
遍历对象。如果值仍然是对象类型,则需要再次调用observer观察方法。
如果设置的新值是对象类型,也需要截取。
//处理对象的拦截
函数定义有效(数据,键,值){
Observer(value) //如果值仍然是对象类型,则需要递归劫持
Object.defineProperty(数据,键,{
get() {
返回值
},
set(newValue){
if(新值===值)返回
值=新值
Observer(newValue) //如果设置的newValue也是对象类型,则需要劫持。
}
})
}
数组的劫持
劫持数组时需要注意以下几点:
Array利用函数劫持的思想(切片编程)截取数据。
数组中新增加的值,如果是对象类型,也需要再次截取。
const oldArrayPrototype=array . prototype
array methods=object . create(oldArrayPrototype)
Constmethods=[push , pop , shift , unshift , splice , sort , reverse ]//可以改变原始数组的方法
methods.forEach(method={
arrayMethods[methods]=函数(.args) {
const result=oldarray prototype[方法]。打电话(这个,参数)
Const ob=this。__ob__ //这是调用方法change的数组。
让插入;//需要再次截取数组中新添加的项的集合。
开关(方法){
案例“推送”:
案例“未移位”:
插入的=参数
外壳“拼接”:
Inserted=args.slice(2) //因为splice的第二个参数后面的内容是新的。
}
如果(已插入){
ob.observerArray阵列(已插入)
}
回送结果
}
})
原理总结
面试中,如果需要手写vue的响应式原理,上面的代码就足够了。但通过研究vue的源代码,如果能在面试中给出以下总结性的回答,就能获得面试官的青睐。
vue 2.0源代码的响应原理:
因为对象是递归截取的,数据层次越深,性能越差。
之所以不使用Object.defineProperty截取数组,是因为数组项太多,性能会很差。
只会拦截数据中定义的数据,后期vm.newObj=xxx 添加的属性不会被拦截。
改变数组的索引和长度不会被截获,所以不会引起视图的更新。
如果需要截取新的属性并改变数据数组的索引和长度,可以使用$set方法。
您可以使用Object.freeze方法来优化数据和提高性能,并且使用此方法的数据不会被set和get方法覆盖。
Vue 3.0源代码响应原则:
3.0版用proxy代替Object.defineProperty,有13种拦截方式。不需要单独处理对象和数组,不需要递归拦截,这是它性能提升最多的地方。
vue 3.0版本中响应原理的简单实现
常量处理程序={
get (target,key) {
if(type of target[key]=== object target[key]!==null) {
返回新的代理(目标[键],处理程序)
}
返回Reflect.get(target,key)
},
集合(目标,关键字,值){
if(key===length )返回true
console.log(更新)
返回Reflect.set(目标,键,值)
}
}
const obj={
arr: [1,2,3],
计数:{数量:1 }
}
//obj是代理的目标对象,handler是配置对象
const proxy=新代理(obj,handler)
关于实现vue的数据响应原理的详细解释,本文到此为止。有关vue数据响应的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。