最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 5分钟了解Vue3 的新特性

    正文概述 掘金(alanyf)   2020-12-06   582

    Vue.js 从 1.x 到 2.0 版本,最大的升级就是引入了虚拟 DOM 的概念,它为后续做服务端渲染以及跨端框架 Weex 提供了基础。本文主要讲的是vue2到vue3.0的优化点。

    vue2.x的痛点

    • 源码自身的维护性;
    • 数据量大后带来的渲染和更新的性能问题;
    • 一些想舍弃但为了兼容一直保留的鸡肋 API 等;
    • TypeScript 支持;

    优化点

    一、使用 monorepo管理源码

    monorepo 把这些模块拆分到不同的 package 中,每个 package 有各自的 API、类型定义和测试。这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确,开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性。

    源码目录

    vue-next
    ├─scripts
    |    ├─build.js
    |    ├─dev.js
    |    ├─utils.js
    ├─packages
    |    ├─global.d.ts
    |    ├─vue
    |    ├─template-explorer
    |    ├─size-check
    |    ├─shared
    |    ├─server-renderer
    |    ├─runtime-dom
    |    ├─runtime-core
    |    ├─reactivity
    |    ├─compiler-ssr
    |    ├─compiler-sfc
    |    ├─compiler-dom
    |    ├─compiler-core
    ├─test-dts
    
    • reactivity:响应式系统
    • runtime-core:与平台无关的运行时核心 (可以创建针对特定平台的运行时 - 自定义渲染器)
    • runtime-dom: 针对浏览器的运行时。包括DOM API,属性,事件处理等
    • runtime-test:用于测试
    • server-renderer:用于服务器端渲染
    • compiler-core:与平台无关的编译器核心
    • compiler-dom: 针对浏览器的编译模块
    • compiler-ssr: 针对服务端渲染的编译模块
    • template-explorer:用于调试编译器输出的开发工具shared:多个包之间共享的内容vue:完整版本,包括运行时和编译器

    二、使用 TypeScript 开发源码

    从vue2中使用的Flow换成了Typescript

    三、性能优化

    1. 源码体积优化

    • 首先,移除一些冷门的 feature(比如 filter、inline-template 等);
    • 其次,引入 tree-shaking 的技术,减少打包体积。

    tree-shaking 依赖 ES2015 模块语法的静态结构(即 import 和 export),通过编译阶段的静态分析,找到没有引入的模块并打上标记。然后压缩阶段会利用例如 uglify-js、terser 等压缩工具真正地删除这些没有用到的代码。

    例如,如果你在项目中没有引入 Transition、KeepAlive 等组件,那么它们对应的代码就不会打包,这样也就间接达到了减少项目引入的 Vue.js 包体积的目的。

    2. 数据劫持优化Proxy

    Object.defineProperty 切换成 es6的Proxy实现

    Proxy 劫持了我们对 observed 对象的一些操作,比如:

    • 访问对象属性会触发 get 函数;
    • 设置对象属性会触发 set 函数;
    • 删除对象属性会触发 deleteProperty 函数;
    • in 操作符会触发 has 函数;
    • 通过 Object.getOwnPropertyNames 访问对象属性名会触发 ownKeys 函数。

    Proxy 劫持的是对象本身,并不能劫持子对象的变化,这点和 Object.defineProperty API 一致。但是 Object.defineProperty 是在初始化阶段,即定义劫持对象的时候就已经递归执行了,而 Proxy 是在对象属性被访问的时候才递归执行下一步 reactive,这其实是一种延时定义子对象响应式的实现,在性能上会有较大的提升。

    3. 编译优化

    • Vue.js 2.x 的数据更新并触发重新渲染的粒度是组件级的,虽然 Vue 能保证触发更新的组件最小化,但在单个组件内部依然需要遍历该组件的整个 vnode 树。

    • vue3做到动静分离,执行diff时仅对比动态节点。

    • 除此之外,Vue.js 3.0 在编译阶段还包含了对 Slot 的编译优化、事件侦听函数的缓存优化,并且在运行时重写了 diff 算法。

    4. diff算法优化

    深度递归遍历vnode树,节点的标签和key相同认为是同一个节点则更新,不同则删除,然后处理子节点。

    子节点分这几种情况处理:纯文本、vnode 数组和空

    1. 空往往意味着添加或删除;
    2. 纯文本相同直接更新innerText,不同则删除;
    3. 新旧子节点都是vnode数组则diff算法来处理;

    vue3.0 diff算法思想

    1. 编译模版时进行静态分析标记动态节点,diff对比差异时仅对比动态节点(性能提升明显);
    2. diff算法先去头去尾,借此缩短遍历对比数组长度(对数组插入和删除操作性能优化明显);
    3. 通过对更新前后子节点数组建立映射表的方式,将O(n^2)复杂度的遍历降低到O(n);
    4. 通过最长递增子序列方法了来diff前后的子节点数组,减少移动操作的次数;
    • vue3.0 diff算法的实现见demo演示
    • 最长递增子序列算法实现:
    /*
     * 寻找最长递增子序列
     * 使用动态规划思想,a -> c = a -> b + b -> c
     * 其中p数组存储的是从p[p[i]] 到 p[i] 的最长递增子序列索引,也就是前一个b的索引;
     * r数组存储最后一个元素也就是c的索引
     */
     function getSequenceOfLIS(arr) {
        const p = [0];
        const result = [0];
        for (let i = 0; i < arr.length; i ++) {
            const val = arr[i];
            const top = result[result.length - 1];
            if (arr[top] < val) {
                p[i] = top;
                result.push(i);
                continue;
            }
            // 二分法搜索
            let l = 0, r = result.length - 1;
            while(l < r) {
                const c = (l + r) >> 1;
                if (arr[result[c]] < val) {
                    l = c + 1;
                } else {
                    r = c;
                }
            }
            if (val < arr[result[l]]) {
                if (l > 0) {
                    p[i] = result[l - 1]
                }
                result[l] = i;
            }
        }
        // 回朔p数组,找出最长递增子序列
        let preIndex = result[result.length - 1];
        for (let i = result.length - 1; i > 0; i --) {
            result[i] = preIndex;
            preIndex = p[preIndex]
        }
        return result;
    }
    

    四、语法 API 优化:Composition API

    1. 优化逻辑组织

    编写组件本质就是在编写一个“包含了描述组件选项的对象”,我们把它称为 Options API,符合直觉思维。

    Options API 的设计是按照 methods、computed、data、props 这些不同的选项分类,当组件小的时候,这种分类方式一目了然;但是在大型组件中,一个组件可能有多个逻辑关注点,当使用 Options API 的时候,每一个关注点都有自己的 Options,如果需要修改一个逻辑点关注点,就需要在单个文件中不断上下切换和寻找。

    Composition API将某个逻辑关注点相关的代码全都放在一个函数里,这样当需要修改一个功能时,就不再需要在文件中跳来跳去。

    2. 优化逻辑复用

    • vue2 有mixin 变量命名容易冲突的问题
    • Composition API 显示的将变量引入当前组件,解决明明冲突问题
    • 简单组件使用Options API,复杂组件使用 Composition API

    建议


    起源地下载网 » 5分钟了解Vue3 的新特性

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元