读官网《Vue 3 迁移指南》

133 阅读5分钟

前言

vue3刚发布的时候,我也在通过其他渠道看了vue3的解读视频(//哎,开课吧个坑爹玩意),当时主讲老师推崇的是阅读vue3的源码和setup的写法的改变。

虽然老师讲的很好,但感觉对于我的工作来说,并没有实际工作效率的提升。(//个人偏见,我真不觉得源码和算法能对实际工作有多大的提升。我更倾向于学习设计模式和普通代码的优化)

昨天看了官网的文档,真心觉得,vue的官方文档比其他库/框架的文档要好太多了,也建议其他没看过官方文档的朋友也翻翻。

我从中发现了一些vue3对于实际开发效率提升的地方,记录一下。这篇文章并不是列举vue3对比vue2的全部更新!

正文

正文顺序按照个人理解的重要程度排列。

单文件组件中的状态驱动的 CSS 变量 (<style> 中的 v-bind)

在.vue文件中,可以用data里边或setup返回的数据直接用在style标签里边了。

本来我还只是觉得这是个小提升,毕竟之前也可以用计算数据绑定template里边的行内样式达到同样的效果。但直到我看了这篇文章,哦,原来这个小提升react没有啊,那可就厉害了,哈哈哈。 「译」为什么我们正在放弃 CSS-in-JS - 掘金 (juejin.cn)

这里贴一段官网的代码,setup同理。

<template>
  <div class="text">hello</div>
</template>

<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>

<style>
.text {
  color: v-bind(color);
}
</style>

Teleport 组件

这是vue3新加的标签,功能是把这个标签里边的内容,挂载到指定的dom里边,简单理解为,子组件主动往祖先组件插入内容,反向slot。官方建议插入到整个vue管控的组件之外。比如body。

他有两个属性:to,disabled。顾名思义,to就是插入进去的地方,可以是css选择器,也可以是一个dom对象。disabled就是禁用这个标签。

这样可以非常简单的设计一个弹窗组件。 之前vue2的时候,设计一个弹窗,还是挺麻烦的,先new一个新的vue实例,并加载到body上,等弹窗关闭的时候,在销毁这个实例,同时把dom从body上清空。这个是B站上用vue2封装的弹窗例子

但是,之前vue的数据都是单向传递的,dom自然也是单纯的父组件包含子组件。Teleport组件却打破了dom单向传递的规则。相信不久就会有人为了图方便,而写出奇奇怪怪的代码。

模板引用 refs | Vue.js (vuejs.org)

As we know。对于在<template>中标记有ref的dom或组件,我们可以用this.$refs来使用。在vue3延续了这个写法,另外在组合式API中,它会对同名的ref赋值。但又有些不同,它实际上是这个组件或dom的onMounted的生命周期,这样,我们在v-for中,就可以这样保存模板:

<template>
    <ul>
        <li v-for="item in list" :ref="el => item.dom = el"> {{ item }} </li>
    </ul>
</template>

这样后期我们就可以在循环数据的时候,直接拿到对应的dom了,非常简单。

Fragments 片段

简单来说就是允许组件没有唯一的根dom。帮助起名字困难户和强迫症解决很大的问题。

<template>
    <header>...</header>
    <main v-bind="$attrs">...</main>
    <footer>...</footer>
</template>

得益于这个设计,那么在<template v-for>中,key就可以直接加在 <template> 上,而不是里边的子元素,这更符合直觉了。

Emits 组件选项

emits:用于声明由组件触发的自定义事件

同时,因为emits的出现, v-on.native 便失去了意义。现在vue会把子组件中没有在emits中定义的事件,当作对于子组件根dom的原生事件。

expose:用于声明当组件实例被父组件通过模板引用访问时暴露的公共属性

如果组件没有定义这个属性,那么就会跟以前一样,整个组件数据和方法都可以被外界使用。如果定义了这个值,那么只有expose包裹的属性和方法才会被外界发现。

个人觉得,这两个API对于实际工作没什么提升,甚至以现在的插件环境来说,还徒增了工作量。但它让公共组件的维护与学习变得简单了,直接看 emitsexposeprops 就能直接使用这个组件了,而不用再费劲写使用文档了。(或者以后用插件直接生成文档?)

删除/deep/>>>

点击标题可跳转至原文。

之前 /deep/>>> 被删除,取而代之的是:v-deep(),同时又新加了两个API

  • :v-slotted() 插值元素
  • :v-global() 全局样式

这样命名更加符合css本身的命名规则。并且新添加了专门处理插值的:v-slotted(),甚至还优化了在<style scoped>不能写全局样式的问题。

但个人觉得对实际编码来说,对开发效率来说提升的并不是特别明显。

组合式api和单文件语法糖<script setup>

这个可以说是vue3最大的改动,也是各位大佬老生常谈的改动,本来这个应该是放到第一位说的,但估计大家看的都烦了,就放到了最后。

在组件中,vue3在vue2的基础上添加了setup生命周期,在beforeCreated之前触发。但和其他的生命周期不同的是,在setup中不能访问this,取而代之的组合式API。这个特殊的生命周期类似于组件的构造函数,可以return出data和methods等。

又因为组合式API几乎可以在setup中完成所有选项API的任务,所以官方提出了<script setup>语法糖。这块建议各位看官方文档

但我个人觉得,既然都提出<script setup>语法糖了,那为什么不更简单一点,像svelte那样,声明变量的时候,去除refreactive的调用,在编译阶段自己加上去?或者未来某个大神重新再写个编译插件?

来自 @vue/runtime-core 的 createRenderer API 用来创建自定义渲染函数

有一个非常经典的面试题是:虚拟dom有什么用?我的回答是:

  1. 避免多次操作dom,提高性能
  2. 通过对于虚拟dom的写不同的渲染解析,抹平各平台的api的差异

现在vue3把这个render方式暴漏出去了,以后像uniapp的的框架会简单很多。

其他

其实还有很多的点没有写到,比如

  • v-if 和 v-for 的优先级
  • v-bind的合并问题
  • 函数组件的部分修改,
  • 去除了eventBus的写法
  • 去除了过滤器filters

但因为我很少用到这些,比如v-if 和 v-for 的优先级,我从来都不把他们放到一个标签上,所以这里就不一一说明了,各位有时间了可以多看看官方文档