# fed-e-task-03-05 **Repository Path**: lv_jing0359/fed-e-task-03-05 ## Basic Information - **Project Name**: fed-e-task-03-05 - **Description**: 拉勾大前端作业:Part3 - 模块五 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-05-19 - **Last Updated**: 2021-05-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 1、Vue 3.0 性能提升主要是通过哪几方面体现的? - 响应式系统升级 - 编译优化 - 源码体积的优化 2、Vue 3.0 所采用的 Composition Api 与 Vue 2.x使用的Options Api 有什么区别? - Options API - 包含一个描述组件选项(data、methods、props 等)的对象 - Options API 开发复杂组件,同一个功能逻辑的代码被拆分到不同选项 - Composition API - Vue.js 3.0 新增的一组 API - 一组基于函数的 API - 可以更灵活的组织组件的逻辑 3、Proxy 相对于 Object.defineProperty 有哪些优点? - Proxy 可以直接监听对象而非属性; - Proxy 可以直接监听数组的变化; - Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的; - Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改; - Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利; 4、Vue 3.0 在编译方面有哪些优化? - Vue.js 3.0 中标记和提升所有的静态根节点,diff 的时候只需要对比动态节点内容 - Fragments(升级 vetur 插件) - 静态提升 - Patch flag - 缓存事件处理函数 5、Vue.js 3.0 响应式系统的实现原理? 答:Vue3 使用 Proxy 对象重写响应式系统,这个系统主要有以下几个函数来组合完成的: - 1.reactive: - 接收一个参数,判断这参数是否是对象。不是对象则直接返回这个参数,不做响应式处理 - 创建拦截器对象 handler, 设置 get/set/deleteProperty - get - 收集依赖(track) - 返回当前 key 的值。 - 如果当前 key 的值是对象,则为当前 key 的对象创建拦截器 handler, 设置 get/set/deleteProperty - 如果当前的 key 的值不是对象,则返回当前 key 的值 - set - 设置的新值和老值不相等时,更新为新值,并触发更新(trigger) - deleteProperty - 当前对象有这个 key 的时候,删除这个 key 并触发更新(trigger) - 返回 Proxy 对象 - 2、effect: 接收一个函数作为参数。作用是:访问响应式对象属性时去收集依赖 - 3、track: - 接收两个参数:target 和 key - 如果没有 activeEffect,则说明没有创建 effect 依赖 - 如果有 activeEffect,则去判断 targetMap 集合中是否有 target 属性 - targetMap 集合中没有 target 属性,则 set(target, (depsMap = new Map())) - targetMap 集合中有 target 属性,则判断 target 属性的 map 值的 depsMap 中是否有 key 属性 - depsMap 中没有 key 属性,则 set(key, (dep = new Set())) - depsMap 中有 key 属性,则添加这个 activeEffect - 4、trigger: - 判断 targetMap 中是否有 target 属性 - targetMap 中没有 target 属性,则没有 target 相应的依赖 - targetMap 中有 target 属性,则判断 target 属性的 map 值中是否有 key 属性,有的话循环触发收集的 effect() 具体代码如下: ```javascript const isObject = val => val !== null && typeof val === 'object' const convert = target => isObject(target) ? reactive(target) : target const hasOwnProperty = Object.prototype.hasOwnProperty const hasOwn = (target, key) => hasOwnProperty.call(target, key) export function reactive (target) { if (!isObject(target)) return target const handler = { get (target, key, receiver) { // 收集依赖 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) { result = Reflect.set(target, key, value, receiver) // 触发更新 trigger(target, key) } return result }, deleteProperty (target, key) { const hadKey = hasOwn(target, key) const result = Reflect.deleteProperty(target, key) if (hadKey && result) { // 触发更新 trigger(target, key) } return result } } return new Proxy(target, handler) } let activeEffect = null export function effect (callback) { activeEffect = callback callback() // 访问响应式对象属性,去收集依赖 activeEffect = null } let targetMap = new targetMap() 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) } export function trigger (target, key) { const depsMap = targetMap.get(target) if (!depsMap) return const dep = depsMap.get(key) if (dep) { dep.forEach(effect => { effect() }) } } export function ref (raw) { // 判断 raw 是否是ref 创建的对象,如果是的话直接返回 if (isObject(raw) && raw.__v_isRef) { return } let value = convert(raw) const r = { __v_isRef: true, get value () { track(r, 'value') return value }, set value (newValue) { if (newValue !== value) { raw = newValue value = convert(raw) trigger(r, 'value') } } } return r } export function toRefs (proxy) { const ret = proxy instanceof Array ? new Array(proxy.length) : {} for (const key in proxy) { ret[key] = toProxyRef(proxy, key) } return ret } function toProxyRef (proxy, key) { const r = { __v_isRef: true, get value () { return proxy[key] }, set value (newValue) { proxy[key] = newValue } } return r } export function computed (getter) { const result = ref() // ref 不传参数,返回 undefined effect(() => (result.value = getter())) return result } ```