vue.js响应式原理,vue如何实现响应式

  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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: