也许你已经看过了Vue.js slots的文档。我对这个功能从“为什么你可能需要它”到“没有它我怎么可能工作”的态度转变非常快。
虽然文档已经解释了它的概念,但是这里有一个关于slots
怎么改进应用程序代码库的真实例子。
在我看来,slots
是vue最有用和最有趣的特性之一。虽然这是web组件所推荐的标准,但是我不知道有其他框架已经实现了这一特性。解释slots
的作用很简单,但是很难解释它为什么有用(如果不使用“可组合性”这个术语),所以我要给你一个使用例子。
假设你的app有很多表单,表单包含几个部分:
- 表单头部:包含关于表单的信息
- 表单元素:供用户输入
- 按钮
现在你想要把表单抽象为一个独立组件。你那些使用react和angular的同事告诉你,你需要使用类似React的组合vs继承或者Angular1的Transclude这样的特性,于是你找到了slots的文档。
你创建了这样一个组件:
<!-- FormHelper.vue -->
<form class="form">
<h3>{{ title }}</h3>
<slot></slot><!-- children will go here -->
<button>Submit</button>
</form>
使用方法如下:
<!-- App.vue -->
<form-helper title="Password Reset">
<input type="text" name="name" value="">
<input type="text" name="email" value="">
</form-helper>
这样就可以正常运行了。可是,产品告诉你,一个特定的表单需要一个文本块来获得帮助信息的标题,按钮名要改为“Request”。这超出了“children”能做的范围。
<!-- FormHelper.vue -->
<form class="form">
<h3>{{ title }}</h3>
<div :v-if="hasHelp">{{ helpMessage }}</div>
<slot></slot><!-- children will go here -->
<button>{{ customButtonName }}</button>
</form>
上述代码可能会出现一些问题,如果需要更多按钮、更多交互等等这些情况,怎么办?幸好,vuejs提供了一个更简洁的解决方案:具名slots。于是,你把代码改成下面这样:
<!-- FormHelper.vue -->
<form class="form">
<h3>{{ title }}</h3>
<slot name="help"></slot>
<slot name="elements"></slot><!-- children will go here -->
<slot name="buttons"></slot>
</form>
使用方法:
<!-- App.vue -->
<form-helper title="Request Form">
<div slot="help">
Please ask your manager before requesting hardware.
</div>
<div slot="elements">
<input type="text" name="item_name" value="">
<input type="text" name="item_value" value="">
</div>
<div slot="buttons">
<button type="button" name="button">Request</button>
</div>
</form-helper>
在我看来,关键思想是:
将slots当作传递给子组件的属性。就像传递字符串、整数和对象,而slots是传递一个子dom树,让子组件可以在任何需要的地方使用。
使用slots的其他场景:
- 通用的模态窗
- 类似bootstrap的面板和自定义内容这样的事情
使用slots的更多优点:
- 子组件用于样式和展示,业务逻辑都保留在父元素中。
- 如果没有传递内容给slots,就不会展示东西。这让你可以很好地复用它们,并且只在你想要的slots中传递。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。