Vue 3.0

Vue 3.0

1. 性能比 2.0 快

1.1 优化 diff 算法

在 vue2 中,虚拟 dom 是全量比较的;vue3 中是增量比较的。

在 vue3 中,增加了静态标记 PatchFlag 。在创建 vnode 的时候,会根据 vnode 的内容是否可以变化,为其添加静态标记 PatchFlag 。diff 的时候,只会比较有 PatchFlag 的节点。PatchFlag 是有类型的,比如一个可变化文本节点,会将其添加 PatchFlag 枚举值为 TEXT 的静态标记。这样在 diff 的时候,只需比对文本内容。需要比对的内容更少了。PatchFlag 还有动态 class、动态 style、动态属性、动态 key 属性等枚举值。

1.2 render 阶段的静态提升

render 阶段指生成虚拟 dom 树的阶段。

在 vue2 中,一旦检查到数据变化,就会 re-render 组件,所有的 vnode 都会重新创建一遍,形成新的 vdom 树。

在 vue3 中,对于不参与更新的 vnode,会做静态提升,只会被创建一次,在 re-render 时直接复用

静态提升可以理解为第一次 render 不参与更新的 vnode 节点的时候,保存它们的引用。re-render 新 vdom树时,直接拿它们的引用过来即可,无需重新创建。

1.3 事件侦听缓存

在 vue2 中,我们写的 @click="onClick" 也是被当作动态属性,diff 的时候也要对比。但我们知道它不会变化,比如变成 @click="onClick2",绑定别的值。

在 vue3 中,如果事件是不会变化的,会将 onClick 缓存起来(跟静态提升达到的效果类似),该节点也不会被标记上 PatchFlag(也就是无需更新的节点)。这样在 render 和 diff 两个阶段,事件侦听属性都节约了不必要的性能消耗。

1.4 减少创建组件实例的开销

vue2.x 每创建一个实例,在 this 上要暴露 data、props、computed 这些,都是靠 Object.defineProperty 去定义的。这部分操作还是挺费时的。

vue3.0 中基于 Proxy,减少了创建组件实例的性能开销。

2. 按需编译,体积比 Vue2.x 更小

在 vue3 中,可以如下面引用 vue 的功能函数,如果没有用到 watch,那编译时就会把 tree shaking 掉。

import { computed, watch, nextTick } from "vue";

利用的就是 ES6 模块系统 import/export。

3. Compostion API:组合API/注入API

这里要说到代码的组织方式,传统的网页是 html/css/javascript(结构/样式/逻辑)分离。vue/react 通过组件化的方式,将联系紧密的结构/样式/逻辑放在一起,有利于代码的维护。

compostion api 更进一步,着力于 JavaScript(逻辑)部分,将逻辑相关的代码放在一起,近而有利于代码的维护。

在 vue2 的组件内,使用的是 Option API 风格(data/methods/mounted)来组织的代码,这样会让逻辑分散,举个例子完成一个计数器功能,要在 data 里声明变量,在 methods 定义响应函数,在 mounted 里初始化变量,如果在一个功能较多、代码量较大的组件里,要维护这样一个功能,就需要在data/methods/mounted 反复的切换到对应位置,然后进行代码的更改。

在 vue3 中,使用 setup 函数。如下所示跟 count 相关的逻辑,都放到 counter.js 文件里,跟 todo 相关的逻辑放到 todos.js 里。

import useCounter from './counter'
import useTodo from './todos'

setup(){ 
    let { val, todos, addTodo } = useTodo() 
    let { count, add } = useCounter()  
    return {  
        val, todos, addTodo,  
        count, add, 
    }
}

这就是 Compostion API 最大的特点,以功能为单位的代码组织方式。同时它可以让代码更易重用。

说到重用,Compostion API 的方式也比 mixin 的方式好很多,可以清楚的看到组件使用的数据和方法来自哪个模块,而 mixin 进组件的功能,常常会困惑此功能来自哪个 mixin。

4. 更好的 TS 支持

vue2 不适合使用 ts,原因在于 vue2 的 Option API 风格。options 是个简单对象,而 ts 是一种类型系统、面向对象的语法。两者有点不匹配。

在 vue2 结合 ts 的具体实践中,要用 vue-class-component 强化 vue 组件,让 Script 支持 TypeScript 装饰器,用 vue-property-decorator 来增加更多结合 Vue 特性的装饰器,最终搞的 ts 的组件写法和 js 的组件写法差别挺大。

在 vue3 中,量身打造了 defineComponent 函数,使组件在 ts 下,更好的利用参数类型推断 。Composition API 代码风格中,比较有代表性的 api 就是 ref 和 reactive,也很好的支持了类型声明。

import { defineComponent, ref } from 'vue' 

const Component = defineComponent({  
    props: {    
        success: { type: String },    
        student: {     
            type: Object as PropType,     
            required: true    
        }  
    },  
    setup() {   
        const year = ref(2020)   
        const month = ref('9')      
        month.value = 9 // OK   
        const result = year.value.split('') // => Property 'split' does not exist on type 'number' 
    }
});

5. 自定义渲染 API(Custom Renderer API)

6. 更先进的组件

7. 更快的开发体验(vite 开发构建工具)

在使用 webpack 作为开发构建工具时,npm run dev 都要等一会,项目越大等的时间越长。热重载页有几秒的延迟,但是如果用 vite 来做 vue3 的开发构建工具,npm run dev 秒开,热重载也很快。这种开发体验真是很爽,拒绝等待。

vite 的原理还是用了浏览器支持 import 关键字了,启动项目不用 webpack 构建工具先构建了,浏览器直接请求路由对应的代码文件,代理服务器针对单个文件进行编译并返回。如果请求的文件里还 import 了其他文件,同理浏览器继续发请求,代理服务器返回。就这样实现了 npm run dev 时无需编译,实时请求实时编译。

8. 总结

其他的,数据监听方式变成了 Proxy,消除了 Object.defineProperty 现有的限制(例如无法检测新的属性添加),并提供更好的性能。

vue3 解决了 vue2 的一些问题,大型应用的性能问题、ts 支持不友好问题,自定义渲染 API 解决体系架构存在的问题,如果在 vue3 的基础上实现 weex 框架会好很多。也做出了很多优化,Compostion API 让代码的组织形式更好。vite 开发构建工具让开发体验更好,Tree shaking 让包更小、性能更优。

总的来说 vue3 还是非常棒的,带来了很多非常好的新特性。

Vue.js 文章被收录于专栏

Vue.js

全部评论

相关推荐

杨柳哥:这不是普通人,那这个钱的是天才
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务