# 概述

  • 谈一谈你对 Vue.js 的响应式数据的理解
  • Vue3 出现解决了什么问题?它有哪些优势?
  • Vue3 新特性有哪些
  • vue2 和 vue3 的响应式有什么区别?

谈一谈你对 Vue.js 的响应式数据的理解

Vue 2.x

对象类型:通过 object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)
数组类型:通过 重写更新数组的一系列方法 来实现拦截(对数组的变更方法进行了包裹

Object.definePropertyhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refer...

  • 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项, Vue 将遍历此对象所有的property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter

    • Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及 更低版本浏览器的原因。
  • 当使用这些数据属性时,会进行依赖收集(收集到当前组件的 watcher)

    • 每个组件都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据记录为依赖之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染

存在问题:

  • 新增属性、删除属性,界面不会更新
  • 直接通过下标修改数组,界面不会自动更新

更多精彩内容,请微信搜索“前端爱好者戳我 查看

Vue 3.x

通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写,属性的增加,属性的删除等。

通过Reffect(反射): 对源对象的属性进行操作

Proxy 是 ECMAScript 6 中新增的属性。【https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refer...

MDN文档中描述的 ProxyReflect

proxy

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

被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。

语法

const p = new Proxy(target, handler)

参数:

target:

要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler:

一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

new Proxy(data,{
  //拦截读取属性值
  get(target, prop){
    return Reflect.get(target, prop)
  },
  //拦截设置属性值或添加新属性
  set(target, prop, value){
    return Reflect.set(target, prop, value)
  },
  //拦截删除属性
  deleteProperty(target, prop){
    return Reflect.deleteProperty(target, prop)
  }
})

Reffect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。Reflect不是一个函数对象,因此它是不可构造的。

reffect身上,就有defineProperty()这个方法

在Vue3数据的更新是proxy配合Reffect来实现的。

Proxy 与 Object.defineProperty 优劣对比

Proxy 的优势如下:

  • Proxy 可以直接监听对象而非属性;
  • Proxy 可以直接监听数组的变化;
  • Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是Object.defineProperty 不具备的;
  • Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
  • Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;

Object.defineProperty 的优势如下:

  • 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue3.0才用 Proxy 重写。

总结

  • 在Vue2中,数据响应式主要借助Object.defineProperty()来实现,存在的缺陷是无法操作数据的增加和删除,
  • 在Vue3中,数据响应式主要借助proxyReffect配合实现,可以做到实现数据的增删改查。

Vue3 出现解决了什么问题?它有哪些优势?

Vue2 代码模式下存在的几个问题:

  • 随着功能增加,复杂的组件代码越来越多,变得难以维护。主要原因是 vue2 通过选项式API组织的代码,一个逻辑功能可能有多处代码,不易别人上手。
  • 缺少一个比较干净的在多个组件之间可以提取和复用逻辑的机制。
  • 类型推断不友好。
  • 没有静态类型检查,只有代码运行之后才能发现错误等等。

Vue3 是在 Vue2 的基础上进行了一些优化,对 typeScript 有了更好的支持。

Vue3 和 Vue2 是可以共存的,Vue3 能够向下兼容支持选项式 API ,同时又新增了一些特性,大大提升了性能。

Vue3 的优势:

  • 性能更好
  • 体积更小
  • 更好地 ts 支持
  • 更好的代码组织
  • 更好的逻辑抽离
  • 更多新的功能

Vue3 新特性有哪些

性能提升

响应式性能提升,由原来的 Object.defineProperty 改为基于ES6的 Proxy ,使其速度更快,消除警告。
重写了 Vdom ,突破了 Vdom 的性能瓶颈。
进行模板编译优化。
更加高效的组件初始化。

更好的支持 typeScript

有更好的类型推断,使得 Vue3 把 typeScript 支持得非常好。

新增Composition API

Composition API 是 vue3 新增的功能,比 mixin 更强大。它可以把各个功能模块独立开来,提高代码逻辑的可复用性,同时代码压缩性更强。

新增组件

  • Fragment 不再限制 template 只有一个根几点。
  • Teleport 传送门,允许我们将控制的内容传送到任意的 DOM 中。
  • Supense 等待异步组件时渲染一些额外的内容,让应用有更好的用户体验。

Tree-shaking:支持摇树优化

摇树优化后会将不需要的模块修剪掉,真正需要的模块打到包内。优化后的项目体积只有原来的一半,加载速度更快。

Custom Renderer API: 自定义渲染器

实现 DOM 的方式进行 WebGL 编程。

vue2 和 vue3 的响应式有什么区别?

vue2 的响应式原理:

对象:是通过 Object.defineProperty 对 对象的已有属性值的读取和修改进行劫持。

Object.defineProperty( 
  'data', 'count', { get(){   }, set(){    }
})

存在的问题:对象直接添加新属性或删除已有属性的时候,界面不会自动更新。

数组:是通过重写数组更新数组一系列更新元素的方法,来实现元素修改的劫持。

// 伪代码const originalProto = Array.prototypeconst arrayProto = Object.create(originalProto)

['push','pop','shift','unshift','splice','reverse','sort'].forEach(key=>{
 arrayProto[key] = function(){
  originalProto[key].apply(this.arguments)
  notifyUpdate()
 }
})

存在问题:直接通过下标替换元素或更新length的时候,界面不会自动更新。

针对 vue2 对象和数组的某些更新,界面不能自动更新的问题,vue2 通过 $set 方法,实现视图的实时更新。

vue3的响应式原理:

vue3 响应式是使用 ES6 的 proxyReflect 相互配合实现数据响应式,解决了 vue2 中视图不能自动更新的问题。

proxy 是深度监听,所以可以监听对象和数组内的任意元素,从而可以实现视图实时更新。

参考地址:

前端爱好者


前端老兵
15 声望1 粉丝

你们说这是哪里?