# 概述
- 谈一谈你对 Vue.js 的响应式数据的理解
- Vue3 出现解决了什么问题?它有哪些优势?
- Vue3 新特性有哪些
- vue2 和 vue3 的响应式有什么区别?
谈一谈你对 Vue.js 的响应式数据的理解
Vue 2.x
对象类型:通过 object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)
数组类型:通过 重写更新数组的一系列方法 来实现拦截(对数组的变更方法进行了包裹
Object.defineProperty
【https://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文档中描述的 Proxy 与 Reflect
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中,数据响应式主要借助proxy和Reffect配合实现,可以做到实现数据的增删改查。
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 的 proxy 和 Reflect 相互配合实现数据响应式,解决了 vue2 中视图不能自动更新的问题。
proxy 是深度监听,所以可以监听对象和数组内的任意元素,从而可以实现视图实时更新。
参考地址:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。