# fed-e-task-03-05 **Repository Path**: fed-e-task/fed-e-task-03-05 ## Basic Information - **Project Name**: fed-e-task-03-05 - **Description**: 大前端训练营第三部分模块五(关于Vue3的基础知识) - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-21 - **Last Updated**: 2021-09-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 揭智勇 | Part 3 | 模块五 ## 1、Vue3.0性能提升主要是通过哪几个方面体现的? - 响应式系统提升 - Vue2.x响应式系统核心defineProperty; - Vue3.0响应式系统核心Proxy - 可以监听动态新增的属性 - 可以监听删除的属性 - 可以监听数组的索引和length属性 - 编译优化 - Vue2.x通过标记静态根节点,优化diff的过程; - Vue3.0中标记和**提升**所有的静态根节点,diff的时候只需要对比**动态节点内容**。 - 静态提升 - patch Flag - 缓存事件处理函数 - 增加Fragments - 源码体积 - 移除一些不常用的API - 比如filter过滤器,inline-template - 更好地支持tree-shaking - 比如transition等按需引入 ## 2、Vue 3.0 所采用的 Composition Api 与 Vue 2.x使用的Options Api 有什么区别? - Options API - 包含一个描述组件选项的对象,比如有data,methods,props,computed等选项; - 开发复杂功能时,需要将功能的逻辑代码拆分导不同选项中,比如功能功能,需要拆分到data,mounted,methods,beforeDestory选项中 - Composition API - 基于函数的API,比如有onMounted,computed,watchEffect等函数,setup为入口函数; - 相比Options API,开发复杂功能可以通过一个函数封装功能代码,更好地组织功能逻辑,更高的复用性。 - 更好的类型推导 ## 3、Proxy 相对于 Object.defineProperty 有哪些优点? - 性能提升 - 可以监听新增的属性 - 可以监听删除的属性 - 可以监听数组的index和length属性 ## 4、Vue 3.0 在编译方面有哪些优化? - 提升所有静态根节点,只需要对比动态节点内容; - 缓存事件处理函数 - 增加Fragments功能,也就是组件不是必须要添加一个根节点元素 ## 5、Vue.js 3.0 响应式系统的实现原理? ### 响应式系统基本原理 Proxy对象是实现Vue3.0响应式系统的核心;能够监听对象属性新增,对象属性删除,监听数组的索引和length属性。基于Proxy实现可观察对象如下: ```javascript function reactive (target) { const handler = { get (target, key, receiver) { // 收集依赖 return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { const oldValue = Reflect.get(target,key, receiver) let result = true if(oldValue !== value) { Reflect.set(target, key, value, receiver) // 触发更新 } return result }, deleteProperty(target, key) { const result = Reflect.deleteProperty(target, key) // 触发更新 return result } } return new Proxy(target, handler) } ``` ### 响应式系统的依赖收集及触发更新 ![](https://sls-cloudfunction-ap-guangzhou-code-1252004410.cos.ap-guangzhou.myqcloud.com/%E6%94%B6%E9%9B%86%E4%BE%9D%E8%B5%96.png) - WeakMap用于存储targetMap,key为目标对象,value为depsMap - Map用于存储depsMap,key目标对象的属性,value为dep集合 - Set用于存储dep观察者 ### effect effect函数用于缓存依赖,effect接受一个函数参数,函数为dep,首次调用dep函数触发收集依赖 ```javascript let activeEffect = null // 观察者 export function effect (callback) { activeEffect = callback callback() // 访问响应式对象属性,去收集依赖, 然后会直接调用track函数 activeEffect = null } ``` ### track 用于收集依赖 ```javascript let targetMap = new WeakMap() export function track(target, key) { // 收集依赖函数 if(!activeEffect) return let depsMap = targetMap.get(target) if(!depsMap) { targetMap.set(target, (depsMap = new Map())) } let dep = depsMap.get(key) // 观察者模式 if(!dep) { depsMap.set(key, (dep = new Set())) } dep.add(activeEffect) // activeEffect 为观察者 } ``` ### trigger 用于触发依赖更新 ```javascript function trigger(target, key) { const depsMap = targetMap.get(target) if(!depsMap) return const dep = depsMap.get(key) if(dep) { dep.forEach(callback => { callback() }); } } ``` ### 响应式系统 - 在proxy中的get收集依赖 - 在proxy中的set和deleteProperty触发依赖更新 ```javascript const isObject = val => val !== null && typeof val === 'object' // 判断对象 const convert = target => isObject(target) ? reactive(target) : target // 转换响应式 const hasOwnPeroperty = Object.prototype.hasOwnProperty const hasOwn = (target, key) => hasOwnPeroperty.call(target, key) // 存在属性 function reactive (target) { if (!isObject(target)) return target const handler = { get (target, key, receiver) { // 收集依赖 console.log('get', key) track(target,key) const result = Reflect.get(target, key, receiver) return convert(result) }, set(target, key, value, receiver) { const oldValue = Reflect.get(target,key, receiver) let result = true if(oldValue !== value) { Reflect.set(target, key, value, receiver) // 触发更新 trigger(target, key) console.log('set', key, value) } return result }, deleteProperty(target, key) { const hasKey = hasOwn(target, key) const result = Reflect.deleteProperty(target, key) if(hasKey && result) { // 触发更新 trigger(target, key) console.log('delete', key) } return result } } return new Proxy(target, handler) } ```