前言
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对于实际工作没什么提升,甚至以现在的插件环境来说,还徒增了工作量。但它让公共组件的维护与学习变得简单了,直接看 emits、expose、props 就能直接使用这个组件了,而不用再费劲写使用文档了。(或者以后用插件直接生成文档?)
删除/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那样,声明变量的时候,去除ref和reactive的调用,在编译阶段自己加上去?或者未来某个大神重新再写个编译插件?
来自 @vue/runtime-core 的 createRenderer API 用来创建自定义渲染函数
有一个非常经典的面试题是:虚拟dom有什么用?我的回答是:
- 避免多次操作dom,提高性能
- 通过对于虚拟dom的写不同的渲染解析,抹平各平台的api的差异
现在vue3把这个render方式暴漏出去了,以后像uniapp的的框架会简单很多。
其他
其实还有很多的点没有写到,比如
- v-if 和 v-for 的优先级
- v-bind的合并问题
- 函数组件的部分修改,
- 去除了eventBus的写法
- 去除了过滤器filters
但因为我很少用到这些,比如v-if 和 v-for 的优先级,我从来都不把他们放到一个标签上,所以这里就不一一说明了,各位有时间了可以多看看官方文档