笔记中的笔记,聊聊尤大在vue3.0 beta直播里说了什么

在vue3.0 beta直播过后一天,掘金就有了别人家的笔记,确实笔记做的很好,但是我想在这份笔记上,加上我看直播时的一些感受,去做自己的笔记
(我还是推崇多做自己的笔记,而不是单单只看别人的笔记,写笔记会让自己对知识点更加深刻,即使会花比较多的时间,但一些知识做笔记是很有必要的)

因为直播过后那两天有事,所以今天才把这份笔记整理出来

事实上一个月前我才重新看了去年和前年的vue conf并整理了笔记,这一次的直播也提到了之前提到的一些东西,所以可以先看我之前的笔记,或者去看之前的vue conf再来看这次的直播笔记

直播现在我看已经有录播了,不喜欢看文章的同学可以跳转至https://www.bilibili.com/video/BV1Tg4y1z7FH

那么就开始吧

全新文档RFC

RFC全称request for comment,也就是请求评论
我们可以在github仓库上去查看vue3.0的设计细节,rfc传送门
在这里插入图片描述
当前beta的主要关注点是稳定性和第三方工具,库的支持

亮点

在这里插入图片描述

  • performance:性能的优化,这个在之前的两次vue conf上其实就说到了很多
  • Tree-shaking support:vue的API都支持Tree-shaking,这个在之前的笔记中提到过,在Vue3.0中,采取了ES module imports按需引入的方式,通过这种方式,如果某些API我们不使用的话,最终不会被打包到我们的项目中
  • Composition API:组合API,RFC里面是这么写的

    a set of additive, function-based APIs that allow flexible composition of component logic.
    (翻译:一组附加的、基于函数的API,允许组件逻辑的灵活组合。)

  • Fragment,Teleport,Suspense:新的内置原生功能
  • Better TypeScript support:更强的ts的支持,这个也在之前多次提到过了
  • Custom Render API:第一方暴露的自定义渲染API

一、performance

在这里插入图片描述

  • Rewritten virtual dom implenmentation
    重写了Virtual DOM的实现,让Virtual更快
    之所以保留了Virtual DOM,主要是为了兼容性的考虑,在Vue2.x中有的用户会去手写render函数,甚至会使用JSX,且Virtual DOM提供了一种模板之外的逻辑表达能力
    (事实上我平时一直都是使用模板语法的,但是在react中采用JSX后,个人看法会觉得通过js来做一些逻辑表达,有时会更加灵活)
    尤大也提到这样可以让一些库的作者去脱离模板,去实现相对复杂的渲染逻辑(私以为就是保留了一个灵活性)
    而对于Virtual DOM的变快,实际上在之前的笔记提到了,VIrtual DOM本身在每次更新时,都会进行一次比对渲染,变快就是通过在更新时对模板进行一个分析,只比对其中会变换的部分,生成更加优化的Virtual DOM Render函数,以此来加快Virtual DOM
  • Compiler-informed fast paths:编译模板的优化,也就是刚才说的,VIrtual DOM变快的原因
  • More efficient component initialization:组件初始化更高效
  • 1.3~2x better update performance:1.3到2倍的update性能提升
  • 2~3x faster SSR:服务器渲染也进行了重写,提高了2到3倍的速度

上面的速度提升是基于一个benchmarks可以说是标准检查程序来测试的,所以与实际项目中还有出入

我们可以到这个地址https://vue-next-template-explorer.netlify.app/,看看模板对应会生成什么代码,帮助我们更好地理解
在这里插入图片描述
那么,我们来根据这个谈谈之前说到的一些vue的更新
下面我要举的一些例子,有的和直播一样,有的是我自己去尝试的,理解可能参杂了我个人的观点,如果有什么地方是理解有误,欢迎大家指出

对模板分析diff时跳过静态节点

之前我们提到了,在vue3.0里面,我们对模板编译的时候进行了分析,使得在组件更新时只去diff会更改的部分,这在生成的代码里面就可以看出来了

我们写入下面的模板语法

<div>
  <span>static</span>
  <span>
    {{msg}}
  </span>
</div>

在这里插入图片描述

我们可以看到红色方框里面的东西,vue在编译的时候,通过分析,通过给创建节点的方法_createVNode传入的第三个参数,来标示出对这个节点,需要比对什么内容,而这里可以看到,对于一个没有使用data中数据的<span>static</span>,在调用方法时传入了一个字符串,表示了这是一个静态内容,而对于使用了data中数据的<span>{{msg}}</span>,则调用了一个方法_toDisplayString,然后在第四个参数,我们可以称为PatchFlag(从GitHub上源文件看到的),传入1标志对于这个节点,只需要比对text即文本即可

我们可以尝试去添加class,id,等来尝试这个表示会变成什么
在这里插入图片描述
在绑定了class后,PatchFlag变为3,我也做过一些尝试了,文本的话会加1,class会加2,如果有其他的属性,则加8,如下面加了id
在这里插入图片描述
除了标志的变化外,加入class(这里我的尝试只知道class)外的其他属性,加添加的时候都会使标志加8(只要出现一个就加8,不会重复添加),然后会在第5个参数传入一个数组,标示哪些属性需要被diff比较,如果我们没有对属性做任何绑定,那么该标志就不会增加,如下
在这里插入图片描述
编译器将class和id视为静态的,那么在更新时就不会去对其进行一个diff
这种编译方式,看似增加了工作(对动态节点的判断以及传入一些相应的会改变的属性),但是在运行时,特别是项目比较大的时候,会有比较大的提升
比如我们看下面的这段内容
在这里插入图片描述
在这一段模板当中,包含了很多的静态节点,在默认的diff算法中,我们需要对这些节点,进行一个diff的比对,这样在大的项目中就会造成runtime运行时的增加,而实际上,这也是Virtual DOM diff算法中最耗时的部分

vue的编译器以这种方式,让我们的runtime即运行时得到有效的减少

对于PatchFlag,有下面这些情况

export const PatchFlagNames = {
  [PatchFlags.TEXT]: `TEXT`, // 1 带有动态textcontent的元素
  [PatchFlags.CLASS]: `CLASS`, // 1<<1 即2 带有动态class的元素
  [PatchFlags.STYLE]: `STYLE`, // 1<<2 即4 带有动态style样式的元素
  [PatchFlags.PROPS]: `PROPS`, // 1<<3 即8 其他属性 表示具有非类/样式动态道具的元素
  [PatchFlags.FULL_PROPS]: `FULL_PROPS`, // 1<<4 即16 表示带有动态键的道具的元素,与上面三种相斥
  [PatchFlags.HYDRATE_EVENTS]: `HYDRATE_EVENTS`, // 1<<5 即32 表示带有事件监听器的元素
  [PatchFlags.STABLE_FRAGMENT]: `STABLE_FRAGMENT`, // 1<<6 即64 表示其子顺序不变的片段
  [PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`, // 1<<7 即128 表示带有键控或部分键控子代的片段
  [PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`, // 1<<8 即256 表示带有未加密子级的片段
  [PatchFlags.NEED_PATCH]: `NEED_PATCH`, // 1<<9 即512 表示只需要非属性补丁的元素,例如ref
  [PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`, // 1<<10 即1024 表示具有动态插槽的组件
  [PatchFlags.HOISTED]: `HOISTED`, // -1 表示悬挂的静态vnode,即永远不用更新
  [PatchFlags.BAIL]: `BAIL` // -2 一个特殊的标志,指代差异算法
}

我们可以在github上找到对应的ts代码
通过上面的数值我们也可以明显看到,这是通过位运算来标识元素中有哪些动态的内容

如果我们勾选右上角options里面的hoistStatic可以更清晰地看到静态节点被提升到渲染函数的外部
在这里插入图片描述
勾选之后,看看这段模板对应的代码
在这里插入图片描述
可以看到,静态的内容被我们提升到了渲染函数外,而在渲染的时候,我们将这些静态的内容传入,这就使得我们只需要在第一次创建的时候去生成这些节点,在后面更新的时候只需去传入这些节点,这样做让我们不用重复创建节点,同时也能做到更好的diff,使性能得到提高。同时,因为只需创建一次,不需要我们在运行更新时先创建新的再销毁旧的,使得内存也得到了优化。

事件监听缓存 cacheHandles

vue3.0提供了cacheHandles这个功能,我们先看看,如果我们不启用这个功能,模板会编译成什么样子
在这里插入图片描述
我们可以看到,onClick被视为一个动态的属性绑定,这是因为我们无法确定这个onclick是否存在于data上面,如果它存在于data上面,那么它可能会发生一个更改,这就导致了我们需要在进行diff算法时对它进行一个比对
而当我们启用了cacheHandles后
在这里插入图片描述
可以看到,模板编译成的代码变成了下图这样
在这里插入图片描述
这里我们对这个onclick进行了一个缓存处理,当第一次我们渲染这个节点的时候,因为不存在_cache[1],所以vue会自动生成一个内联函数,给_cache[1]赋值_cache[1] = $event => (_ctx.onclick($event)),使我们能自动去调用组件上最新的onclick,这样,在后续的更新中,我们只需要从缓存_cache[1]中去读取同一个函数,而既然是同一个函数,那也没有被更新的必要了,所以这个@click会被看为是静态的。
此外,在@click中我们是可以写入一个内联函数的,vue3.0会通过静态分析,如果@click的值是可以被缓存的,就会做一个缓存,如下面这段带有内联函数的模板
在这里插入图片描述
这种优化在要给组件传入一个函数时尤为明显,如果不使用事件监听缓存的话,那么在父组件更新的时候,子组件就会跟着更新,而通过事件监听缓存机制,我们传给子组件的函数,它会在调用时动态地去找到组件中最新的那个函数,就比如上面的例子中,我们会去调用到组件中最新的click方法,不需要对子组件进行一个更新

实际上在React中,useMemo就有类似的功能,React文档中的useMemo是这么写的

把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

SSR渲染优化

在这里插入图片描述
在进行SSR渲染时,会在服务端尽可能地将静态部分处理为字符串返回
在这里插入图片描述
可以看到,左边的html直接变为字符串推入,而如果存在有动态节点,也会尽可能地将动态节点放在字符串里面
在这里插入图片描述
可以看到,这里的id是动态绑定的,msg内容也是动态的textContent,而这里编译成代码时,使用了模板字符串,最终还是以一个字符串的内容推入

针对过深的静态节点采用innerHtml插入字符串

即使不使用SSR,在客户端方面,如果我们的静态节点嵌套地足够深的话,那么对于这段静态节点内容,就会使用_createStaticVNode去直接将一段字符串插入
在这里插入图片描述
这里要注意的是,是嵌套的层数多的时候会引起这种编译方式的改变,静态节点多并不会引起这种改变
在这里插入图片描述
我这里写了100个静态节点,但仍然没改变编译方式
而一旦嵌套的节点里面有一个动态节点,那么不会和SSR一样仍然使用字符串,而是会变回原来的编译方式
在这里插入图片描述
但即便如此,对于嵌套深的节点来说,比起我们对每个节点一个个append,使用innerHTM的方式让我们又得到了性能上的提升

展示的优化数据

在这里插入图片描述

二、Tree-shaking

在这里插入图片描述

  • 使更多可选的内容可以被tree-shaking,比如v-model和<transition>现在就可以被tree-shaking了,没有用到的时候,打包就不会被放入项目中
  • 模板中只包含一个简单的Hello World时,框架为项目带来的大小只增加了13.5kb
    • 如果采用了Composition API支持替代其他options的API的话,会变成11.75kb大小,在vue3.0中为了兼容之前版本,默认不会把options的API去掉,但是会有开关提供把这些API去掉的选项
      (options API存在的问题在于,我们无法去判断这个API有没有用到,因为无法去对js进行一个分析)
  • 即便是vue3.0的东西都放进去,也只有22.5kb(包括所有的新功能)
    • 这个大小比vue2.x小,但功能却更多

我们知道,webpack等一些打包工具,本身是具备tree-shaking能力的
(tree-shaking可以理解为在打包的时候,将一些无用的内容去掉,不添加到打包好的文件里,使项目体积变小)
但是要使用tree-shaking,前提是我们使用ES module来进行引入,在vue3.0里面,有更多的内容需要当我们使用import的时候,才会被打包进项目里,比如上面ppt里的v-model和transition
我们可以看看,当我们不使用任何东西的时候在这里插入图片描述
可以看到,当我们没有使用任何东西的时候,就理所当然不会import任何东西(当然这也是不可能的,我们不用vue的功能引入vue这个框架干嘛)
但只要我们但凡写入一个标签,就会import需要的内容
在这里插入图片描述
那么,我们试着使用v-model,就会引入v-model相关的内容
在这里插入图片描述
可以看到,这里引入了_vModelText来实现v-model的功能,而让我感到惊讶的是,vue3.0不只是对v-model这个功能采用import的方式来使用,它还针对input的类型来进行引用,我们知道input的默认type为text,所以这里引入的是_vModelText,而如果我们将type做一个改变,如下
在这里插入图片描述
可以看到,我们引入的内容发生了变化,从_vModelText变成了_vModelRadio,而如果我们的type是一个动态绑定的话,就会引入所有的model
在这里插入图片描述
我们看到,这里的引用又变成了_vModelDynamic,表示引入了所有类型对应的v-model实现的代码

v-model相关的内容可以在GitHub上的vModel.ts文件里看到,这里实现了多个类型的v-model功能实现,然后使用export暴露出来

三、Composition API

在这里插入图片描述

  • 能和options API一起使用
  • 灵活的逻辑组合与复用
  • 响应式模块可以和其他框架搭配使用

实际上我们完全可以将Composition API视为一个全新添加的API,它不会影响到我们之前的各种API的使用
在vue2.x里面,我们可能会采用mixin来进行逻辑的抽取,但在vue3.0里面不建议使用mixin,推荐使用Composition API

我们可以来https://composition-api.vuejs.org/查看Composition API的内容
我们也可以点击页面右上角的API Reference查看相关API
主要看的有下面六个主要的API
在这里插入图片描述
而这六个API下面的东西(指API文档目录中这六个API下面的内容),很多都是常见的一些工具函数

四、Fragments,Teleport,Suspense

Fragments

在这里插入图片描述

  • 模板里面不再要求需要是一个单独的根节点,甚至于模板可以只是一个纯文本
  • render函数也可以直接返回一个数组
  • just works 这个表示说我们只需要按往常写我们的代码,会让我们感知变化的只是一个根节点可以不再是一个,其他的我们在写代码时不会有感知,所以,just works

Teleport

在这里插入图片描述

  • 以前被称为<Portal>,对标React 的Portal
  • 更多细节将由@Linusborg 分享

Suspense

在这里插入图片描述

  • 等待嵌套树中的嵌套异步依赖项
  • 支持async setup()
  • 支持异步组件

五、更好的TS支持

在这里插入图片描述

  • 有使用ts写的自动类型定义的提示的代码块
  • 在js和ts中API是相同的
    • 事实上,代码也基本相同
  • TSX的支持
  • class组件还会继续支持,但是需要引入vue-class-component@next,该模块目前还处在 alpha 阶段,不是推荐的使用方式

当前有一个vue3 + TS的插件正在开发中,有类型检查和自动补全等功能,当前还在实验性阶段
在这里插入图片描述
后面可能会放到vs code里面的vetur插件,我没弄错的话应该是这个
在这里插入图片描述

六、Custom Renderer API 自定义渲染器API

在这里插入图片描述

  • 正在进行NativeScript Vue集成
  • 用户已经可以尝试使用WebGL自定义渲染器,它可以与普通Vue应用程序一起使用

这个实际上vue2也可以做,之前是通过vue里面一个非暴露的API去实现这样的功能,但问题是这样我们需要去fork vue

用起来简单,可以用来做cli工具

接下来的工作

在这里插入图片描述

Docs & Migration Tools / Guides

文档和升级指南
在这里插入图片描述

Router

在这里插入图片描述
现在有一个vue3兼容的一个alpha,暂时可以用,但不是很稳定
可以通过npm使用,传送门在此
Router有一些API的改动,可以到rfc里面看到相应的改动

Vuex

在这里插入图片描述
vuex@next目前基本没有API改动,因为当前是要先做一个vue3能先用起来的vuex,vuex的下一个版本正在设计中,但短期应该不会放出来

CLI

在这里插入图片描述
现在有一个vue-cli-plugin-vue-next插件,可以帮助生成一个基于vue3的项目

DevTools

在这里插入图片描述
已经可以让现在的DevTools去支持现在vue3的组件树,但是还需要完善,才能拿出来用

Vetur

在这里插入图片描述
应该会在vue3发布前把模板分析之类的功能整合进去

2.x版本还有最后的2.7

在这里插入图片描述

  • 2.x还有最后一个2.7版本要发布
  • 从3.0版本移植兼容性的改进
  • 对一些vue3要移除的内容做出警告
  • LTS 18个月

大概就是这些了,其实里面有一些内容我理解也不是特别清晰,后续去看一些rfc和一些源码后会补充在这篇博客里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值