hook 到底是什么?
ChatGPT 是这样解释 hook 的:在编程中,hook(钩子) 是一个设计模式,它允许开发者在系统执行某些操作时插入自定义代码。换句话说,hook 提供了一种机制,使得你可以在特定事件发生时"挂钩"到程序的某些位置,并执行自定义逻辑。
说的直白一点就是:我们将一系列的自定义逻辑代码封装成为一个函数,然后在需要编写相同逻辑的地方引入该函数并调用,从而实现复用。
Vue2 中的 hook
Vue2 中其实也存在 hook ,那就是 Vue的生命周期钩子函数,通过钩子函数,我们可以将特定的逻辑挂载到特定的时间节点上。特定的逻辑我们可以封装成函数,通过引入之后再调用,这样也可以实现逻辑代码复用。
具体生命周期请参考 -- Vue2 生命周期详解
Vue3 的hook
Vue2 中的配置式生命周期在Vue3中同样可以使用,但是Vue3还有组合式的生命周期,需要在 setup 中使用,它们允许你在特定的生命周期阶段执行代码。
至于完整的组合式生命周期,请参考之前的博文-- Vue3 生命周期 。
除了生命周期 hook 之外,Vue3还可以自定义 hook,我们在自定义 hook 时习惯性的采用 use 开头,类似于 react hook 中的 useState、useCallback、useRef 等等。
具体例子请参考官网文档--鼠标跟踪器示例
Vue3 hook 与 Vue2 mixin 对比
Vue3 中hook 本质上是一个 组合式函数(Composables), 是一个利用 Vue3 的组合式 API 来封装和复用有状态逻辑的函数,也就是把 setup 函数中使用的 Composition API 进行封装。
与之相对的,在Vue2中,也存在一个用于封装和复用的API,那就是 mixin。
mixin 实际上是一个对象,是一个允许你将多个组件共享的逻辑集中到一个独立的对象,避免重复代码。当一个组件使用了 mixin
时,mixin
中定义的选项(如数据、方法、生命周期钩子等)会被"混入"组件的定义中。详情参考 -- Vue mixin 混入
但是这也会带来一些老生常谈的问题:
- 命名问题:在 mixin 中如果定义了相同的选项,如data中的数据,生命周期,计算属性等可能会导致命名冲突,因为 Vue2 在进行混入时,针对于不同的选项混入规则不一样:data 中数据重名后组件内的会覆盖 mixin 中的,生命周期中若存在重名,则会把组件和mixin中的生命周期混成一个数组,两个生命周期钩子都会执行,但是 mixin 先,组件后等等一系列规则
- 多个mixin混入:如果一个组件中存在多个 mixin ,且多个mixin 都需要对数据进行处理,或存在相同的生命周期钩子时,可能会导致逻辑冲突和不可预见的错误。除此之外,当使用了多个 mixin 时,实例上的数据属性来自哪个 mixin 变得不清晰,这使追溯实现和理解组件行为变得困难。
- 依赖管理:mixin 中的某些逻辑可能依赖于组件中的某些数据,但是这是隐性的,并没有事先声明或者引入,这就导致了mixin中或组件中的更改可能会导致程序错误。
而 Vue3 的组合式函数则是解决了上述的问题,因为:
- 组合式函数的函数名称基本不会重复,且通过 return 返回数据,即使数据名称相同,我们也可以通过 对象.属性 的形式使用,不会造成冲突。
- 多个 hook 组合使用,一个组合式函数可以调用一个或多个其他的组合式函数。而组合式函数都是通过return返回数据的,不会导致冲突,这使得我们可以像使用多个组件组合成整个应用一样,用多个较小且逻辑独立的单元来组合形成复杂的逻辑。
- Vue3 通过 return 返回数据,不存在 this,不会导致隐式依赖的问题。
总结
1、Vue3 hook 其本质是一个组合式函数。把 setup 函数中 使用的组合式API进行了封装,得到了一个可复用有状态逻辑的函数
2、Vue2 中的生命周期钩子也是 hook,Vue3 中配置式生命周期、组合式生命周期都是 hook
3、Vue3 中可以自定义 hook,通用的定义名称是 usexxxx
4、Vue3 中的 hook 相比于 Vue2 的mixin,存在明显优点,解决了 mixin 命名重复,依赖管理
多个 mixin 引入等等问题。