zl程序教程

您现在的位置是:首页 >  前端

当前栏目

面试官:说说Vue响应式原理

2023-09-11 14:19:18 时间

前言:

面试过程中大家可能会经常遇到有面试官问“你能说说vue的响应式原理吗?
很多不明就里的人会说是v-model,这里其实面试官想问的是vue能实现响应式使用的是JS中的什么API,而且v-model这个属于双向数据绑定和面试官所问的的vue的响应式原理属于牛头不对马嘴了。
很容易给面试官留下不好的印象,关于v-model的解释,大家可以直接去vue官方看一下,
我们这里主要解析一下vue的响应式原理。
资料来自B站尚硅谷,喜欢vue的小伙伴可以在哔哩哔哩直接搜索尚硅谷的vue教程,里面有一个叫姓张的老师讲的挺好的(具体叫什么名字我忘了),建议大家去B站看看。
接下来我们分别介绍一下vue2和vue3的响应式原理

响应式浅析(谨记加粗的位置)

vue2

vue2的响应式原理主要使用的是Object.defineProperty( ),里面需要传入三个参数,分别是:
【响应源数据的对象,源数据中的需要读写的属性,相对应的对象方法(包含了get和set方法)】

vue3

vue3的响应式原理主要依靠的是ES6新增的 Proxy 以及相配合的 Reflect,需要在Proxy的实例对象中传入两个参数
【源数据对象,处理对象的方法【get,set,deleteProperty…等】

vue响应式原理示例

下面通过两个实例我们分别来看看vue2和vue3的响应式原理

一、vue2响应式原理

vue2响应式简例

//源数据
  let person = {
    name:'张三',
    age:18
  }

  //模拟Vue2中实现响应式
   let p = {}
  Object.defineProperty(p,'name',{
    configurable:true,
    get(){ //有人读取name时调用
      console.log('调用了get方法,获取了name属性')
      return person.name
    },
    set(value){ //有人修改name时调用
      console.log('调用了set方法,修改了name属性')
      person.name = value
    }
  })
  Object.defineProperty(p,'age',{
    get(){ //有人读取age时调用
      return person.age
    },
    set(value){ //有人修改age时调用
      console.log('调用了set方法,修改了age属性')
      person.age = value
    }
  }) 
  console.log(p.name = '李四')  //调用Object.defineProperty中的set方法修改数据
  console.log(p.name)  //调用Object.defineProperty中的get方法获取数据
  

vue2响应式分析总结

在上面的示例中,我们利用了JS对象中的defineProperty()方法对对象person进行了数据劫持。
当我们改变空对象p的时候,可以发现person对象中的数据也在跟着改变,
这种方法的意义主要在于看我们劫持的是person对象中的哪一个数据,通过在defineProperty()传入的第三个参数中定义的get(),set()或者使用delete让我们达到对源数据达到增删改查的目的。
这里面比较特殊的是delete关键字(删除对象某个属性),我们需要使用 【configurable:true】这个参数才能真正的删除数据。
而我们使用console.log()的输出位置就可以我们作为真正更换数据渲染页面时需要做的一些逻辑处理。我们可以直接打开浏览器的控制台,一些简单的增删改查来验证这个响应式

二、 vue3响应式原理

vue3响应式简例

  //模拟Vue3中实现响应式
  //源数据
  let person = {
    name:'张三',
    age:18
  }
  const p = new Proxy(person,{
    //有人读取p的某个属性时调用
    get(target,propName){
      console.log(`有人读取了p身上的${propName}属性`)
      return Reflect.get(target,propName)
    },
    //有人修改p的某个属性、或给p追加某个属性时调用
    set(target,propName,value){
      console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
      Reflect.set(target,propName,value)
    },
    //有人删除p的某个属性时调用
    deleteProperty(target,propName){
      console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
      return Reflect.deleteProperty(target,propName)
    }
  })
  console.log(p.name) //读取到name的时候会调用实例身上的get方法
  console.log(p.name = '李斯特') //修改name的时候调用实例身上的set方法
  console.log(p.name) //读取到name的时候会调用实例身上的get方法获取到的是修改后的数据
  console.log(delete p.age) //删除属性的时候会调用deleteProperty方法

vue3响应式分析总结

通过上面的一个简单示例,我们可以清楚发现,vue3的响应式相对于vue2来说简洁了很多,主要体现的地方就是我们用了Proxy的实例对象之后,不需要在单独的想vue2之中那样(使用的defineProperty)需要特意去指定监控某个对象的变化(name、age属性)。这个是很重要的一个变化。我们一定要谨记。希望能看到这里小伙伴以后面试遇到该类问题的时候都能轻松惬意娓娓道来。

最后

这是本人对vue响应式原理的一个简单认识,如果有什么地方不正确或有所遗漏的,期待您的批评指正。
数风流人物,还看今朝。希望风华正茂的我们都能在自己喜欢的工作岗位上发光发热,积极向上。做一个稻盛和夫先生所说的 “自燃型” 的人