Reference: Utilize the File Structure to Decide When to Use Vue.js Slots
如果你有时难以确定是应该使用插槽还是直接导入组件,那么本文适合你哦。 我们将学习如何利用文件结构来帮助我们决定何时使用插槽。
让你的文件结构来决定是否应该使用插槽
思考一下,下面这个文件的树形结构:
你想创建一个卡片组件(BaseCard.vue)来展示产品的详细信息(ProductDetails.vue),你不该做的是,直接在BaseCard组件上引入or修改ProductDetails(如下图所示),或者说是你不应该在抽象的组件中引入具体的组件,在公共/通用的组件中包含某个特殊/具体的组件。
你应该去考虑应用IOC(Inversion of Control principle 反转控制)
Vue中的插槽(slots)可以理解为是一种依赖注入(Dependency Injection)的形式。相比于直接在某个组件中引入另外一个组件这种强耦合(tightly couple)的方式,你可以使用slots来实现组件间的解耦,如下图所示:
通用基础的组件不应该依赖具有某特定功能的组件。但应用起来不是这么的直截了当,或者说是简单明了,很多情况下,你要去比较,去思考,是要用slots来解耦组件更好,还是就将两个或多个组件强关联的方式才是更好的。
在选择强耦合还是松散耦合的方式时,文件的结构可以在一定程度上帮助我们决策。在上面的示例中,我们可以看到BaseCard嵌套的深度比ProductDetails深一级。 那么把这个模式扩展应用到不同的组件,我们可以制定如下的规则:
切勿从父目录导入组件(Never import components from a parent directory.)
还是上面这个例子,BaseCard组件中不允许引入其父目录中的任何组件,但是ProductDetails组件是被允许引Base里的组件的
域驱动设计(Domain-Driven Design)
假设我们要使用域驱动设计来构建应用程序, 在这种情况下,我们可以创建一个模块目录,这个模块目录包含各组件和各具体的功能实现等,如下如图所示:
根组件是可以引入base和modules目录中的组件的;base目录下的组件只能引用其目录内的组件。
如果一个模块需要引用BaseCard组件,我们可以通过sot的方式引入或者其他依赖注入的方式来实现
这样的话,我们可以获得以下好处:
- 完全解耦的组件
- 实现模块的共享(跨项目或微前端)
- 组件明确指明了它需要哪些依赖项
- 组件不依赖于某个功能或依赖项的特定的实现,而仅依赖于它们所暴露的具体的接口。
回到上面的例子,在该项目里,组件可以分为三种类型:
- 基础组件(Base components)里放的是你项目中最通用,最公共的部分。它们可以被轻松的重用,也可以支持跨项目的调用(比如,BaseButton,BaseCard,BaseDialog)
- 根级组件(Root level components)既可以包含通用的,也可以包含某特定的组件,但是它们都是特定于你的项目/应用程序的。(比如 TheHeader,TheSidebar,PromoBlackFriday)
- 模块组件(Module components)是专注于包括某特定、具体的功能的组件(比如,ProductList,ArticleBody,ShoppingCartTotal)
如果我们决定遵循这一规则,我想说的是,我们应该始终遵循Never import components from a parent directory,当然也会有例外,比如对于那些通用的构建基块,我们可能会决定打破规则,但前提是这对我们的项目有意义。
另一方面,例外也是可以接受的,比如一个组件是可以为其同级或者比它嵌套更深的组件提供插槽的
请记住,例外总是难以去阐释的,而太多的例外会导致混乱尤。
遵循此规则对于某些类型的项目可能会有所帮助, 但是请记住,这在很大程度上取决于具体情况,要具体情况具体分析哦~