前文再续:【?万字警告】了不起的 Vue3(上)
一起看看 Vue3 给我们带来了哪些值得关注的新东西。
Composition API
首先当然是万众瞩目的 Composition API。
为此,我搬运了然叔的一夜动画~
我们先回顾一下在 Vue2 中 OptionsAPI 是怎么写的:
随着产品迭代,产品经理不断提出了新的需求:
由于相关业务的代码需要遵循 option 的配置写到特定的区域,导致后续维护非常的复杂,代码可复用性也不高。最难受的是敲代码的时候不得不上下反复横跳,晃得眼瞎...
用了 CompositionAPI 会变成什么样呢?
我们可以看到,功能相关的代码都聚合起来了,代码变得井然有序,不再频繁地上下反复横跳。但还差点意思,事实上,我们很多逻辑相关的操作是不需要体现出来的,真正需要使用到的可能只是其中的一些变量、方法,而 Composition API 带来的出色代码组织和复用能力,让你可以把功能相关的代码抽离出去成为一个可复用的函数 JS、TS 文件,在. vue 文件中通过函数的调用把刚刚这些函数的返回值组合起来,最后返回模板真正需要使用到的东西:
巴适得很~
Composition API 为何这么好用,得益于它的两个核心组成:
- Reactivity——响应式系统
- 生命周期钩子
响应式系统暴露了更多底层的 API 出来,从而让我们很轻松地去创建使用响应式变量。然后结合暴露出来的生命周期钩子,基本就可以完成整个组件的逻辑运作。当然还可以结合更多的 api 完成更复杂的工作,社区也有很多关于 CompositionAPI 的使用技巧和方法,这一块就不去细化了,点到为止。
优势
对比 Class API:
更好的 TypeScript 类型推导支持
function 对于类型系统是非常友好的,尤其是函数的参数和返回值。
代码更容易被压缩
代码在压缩的时候,比如对象的 key 是不会进行压缩的,这一点可以从我们刚刚对于 Three shaking demo 构建出来的包就可以看得出来:
而 composition API 声明的一些响应式变量,就可以很安全地对变量名进行压缩。
Tree-shaking 友好
CompositionAPI 这种引用调用的方式,构建工具可以很轻松地利用 Tree shaking 去消除我们实际未使用到 “死代码 “
更灵活的逻辑复用能力
在 Vue2 中,我们一直缺少一种很干净方便的逻辑复用方法。
以往我们要想做到逻辑复用,主要有三种方式:
- 混入——Mixins
- 高阶组件——HOC
- 作用域插槽
为了更好地体会这三种方法的恶心之处,我用一个简单的 demo 去分别演示这三种方法。
案例:鼠标位置侦听:
先看看 Mixins 的方式:
Mixins
MouseMixin.js:
import {throttle} from "lodash"
let throttleUpdate;
export default {
data:()=>({
x:0,
y:0
}),
methods:{
update(e){
console.log('still on listening')
this.x = e.pageX
this.y = e.pageY
}
},
beforeMount() {
throttleUpdate = throttle(this.update,200).bind(this)
},
mounted() {
window.addEventListener('mousemove',throttleUpdate)
},
unmounted() {
window.removeEventListener('mousemove',throttleUpdate)
}
}
复制代码
使用:
获取鼠标位置——Mixins
获取鼠标位置——Mixins
(
"x">{
{ x }}
,
"y">{
{ y }}
)
复制代码
当大量使用 mixin 时:
- ❌ 命名空间冲突
- ❌ 模版数据来源不清晰
HOC——高阶组件
HOC 在 React 使用得比较多,它是用来替代 mixin 的方案。事实上 Vue 也可以写 HOC。
其原理就是在组件外面再包一层父组件,复用的逻辑在父组件中,通过 props 传入到子组件中。
看看这个带有可复用逻辑的 MouseHOC 怎么写:
import Mouse2 from "@/views/Mouse/Mouse2.vue";
import { defineComponent } from "vue";
import { throttle } from "lodash";
let throttleUpdate;
export default defineComponent({
render() {
return (
);
},
data: () => ({
x: 0,
y: 0,
}),
methods: {
update(e) {
this.x = e.pageX;
thi