在 setup 那一小节中,我们知道,setup 在调用时,组件实例还未创建,那意味着我们无法使用 this 访问当前实例,那我想通过 this 在 vue2 中访问一些内置属性,怎么办?比如 attrs 或者 emit。我们可以通过 setup 的第二个参数:
setup(props, context) { do anything... }
这个 context 对象也是一个 Proxy 对象,当我们通过 context.attrs 访问其属性时,本质上代理对象会将访问指向组件的内部实例(即之间文章中提及的 componentInternalInstance)。
生命周期
每一个 vue2 中的组件生命周期函数,当前都对应一个生命周期 hook,比如:
import { onMounted, onUpdated, onUnmounted } from "vue"; setup() { onMounted(() => { ... }); onUpdated(() => { ... }); onUnmounted(() => { ... }); }
这里值得注意的一点在于,对于 beforeCreate 和 created 生命周期,虽然有响应的 hook,但是我觉的没有必要单独使用了,因为这些逻辑代码大部分是一些初始化逻辑的代码,直接写在 setup 方法中即可。
如何复用代码
在这个基础上,复用代码的方式也不再像 vue2 中的那样,通过 mixin 或者 HOC 来达到复用代码的目的,这里稍微说一下,这些复用代码方式中比较显著的缺点有:
隐藏了数据来源,主要体现在 mixin 中
会牺牲一些性能,主要体现在 HOC 中
可能会遇到命名冲突问题,主要体现在 mixin 中
在 vue-next 中,复用代码的逻辑本质上是利用这些 hook 来拆分业务逻辑与状态,如果你比较熟悉 react hooks 的话,应该很快就能明白我指的是什么意思。如果我们将逻辑都写在 setup 方法中,很快代码就会变得难以维护,在这方面,我们可以将一些耦合在一起的代码抽离出来,同时以 use 前缀命名,声明一个自定义的 hook,如下:
export default { setup() { const data = useSearch() const { sortedData, sort } = useSorting(data) return { data, sortedData, sort } } } function useSearch() { ...fetch data } function useSort(data) { ...sort data }
除了以 inline 的方式来声明,还可以将这些自定义的 hook 声明在单独的文件中,直接通过 import 导入即可,比如:
import useSearch from '@hooks/search' import useSort from '@hooks/sort'
与 react hooks 对比
vue-next 在这方面借鉴了 react hooks 的设计思想,但是从实现层来讲,它们是不一样的,主要有以下几点:
vue-next 不依赖于其调用顺序,而 react 依赖
vue-next 提供了生命周期方法,而 react 刻意模糊生命周期的概念
vue-next 基于响应式系统实现,意味它的依赖不需要显示声明(而且是自动的),而 react 需要手动声明依赖数组