软件编程有一个重要的原则是 D.R.Y(Don’t Repeat Yourself),讲的是尽量复用代码和逻辑,减少重复。组件扩展可以避免重复代码,更易于快速开发和维护。那么,扩展 Vue 组件的最佳方法是什么?
Vue 提供了不少 API 和模式来支持组件复用和扩展,你可以根据自己的目的和偏好来选择。
本文介绍几种比较常见的方法和模式,希望对你有所帮助。
扩展组件是否必要
要知道,所有的组件扩展方法都会增加复杂性和额外代码,有时候还会增加性能消耗。
因此,在决定扩展组件之前,最好先看看有没有其他更简单的设计模式能完成目标。
下面几种组件设计模式通常足够替代扩展组件了:
props 配合模板逻辑
slot 插槽
JavaScript 工具函数
props 配合模板逻辑
最简单的方法是通过props结合模板条件渲染,来实现组件的多功能。
比如通过 type 属性:
MyVersatileComponent.vue
使用组件的时候传不同的type值就能实现不同的结果。
// ParentComponent.vue
如果出现下面两种情况,就说明这种模式不适用了,或者用法不对:
组件组合模式把状态和逻辑分解成原子部分,从而让应用具备可扩展性。如果组件内存在大量条件判断,可读性和可维护性就会变差。
props 和模板逻辑的本意是让组件动态化,但是也存在运行时资源消耗。如果你利用这种机制在运行时解决代码组合问题,那是一种反模式。
slot(插槽)
另一种可避免组件扩展的方式是利用 slots(插槽),就是让父组件在子组件内设置自定义内容。
// MyVersatileComponent.vue
Common markup
// ParentComponent.vue
Inserting into the slot
渲染结果:
Common markup
Inserting into the slot
这种模式有一个潜在约束, slot 内的元素从属于父组件的上下文,在拆分逻辑和状态时可能不太自然。scoped slot会更灵活,后面会在无渲染组件一节里提到。
JavaScript 工具函数
如果只需要在各组件之间复用独立的函数,那么只需要抽取这些 JavaScript 模块就行了,根本不需要用到组件扩展模式。
JavaScript 的模块系统是一种非常灵活和健壮的代码共享方式,所以你应该尽可能地依靠它。
MyUtilityFunction.js
export default function () {
…
}
MyComponent.vue
import MyUtilityFunction from “./MyUtilityFunction”;
export default {
methods: {
MyUtilityFunction
}
}
扩展组件的几种模式
如果你已经考虑过以上几种简单的模式,但这些模式还不够灵活,无法满足需求。那么就可以考虑扩展组件了。
扩展 Vue 组件最流行的方法有以下四种:
Composition 函数
mixin
高阶组件(HOC)
无渲染组件
每一种方法都有其优缺点,根据使用场景,或多或少都有适用的部分。