背景
最近重新回归了前端开发,在开发过程中发现在组件封装过程中slot使用频率相当的高,像比较主流的Element UI
也是提供了不少的插槽来帮助用户来更灵活的开发,本着学习知识以及和大家一起共同提高的态度,把自己对于slot组件的理解写成文章和大家一起分享。
深入浅出小插槽
如果对于slot的基本概念已经十分了解了,可以跳过该段落,如果你不是很确定,建议读完本段落。
语法比较简单,通过子组件中添加 | 代码块 并且在父组件调用过程中使用默认插槽或者具名插槽来增加或者替换默认插槽内容。详情见官网。
我理解的插槽是父子组件关系中,插槽在子组件中展示位置以及展示内容的操作手段,父组件决定展示内容,子组件决定展示位置。不理解?继续往下走走:
子组件 layout.js
<template>
<div>
<slot name="header" :header="headerName"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'layout',
data() {
return {
headerName: 'inside name'
}
}
}
</script>
父组件home.js
<template>
<layout>
<!--[v-slot:header]标识此为替换name为header的插槽, props则是子组件中通过 :header绑定过来的参数-->
<template v-slot:header="props">{{props.header}}</template>
<template>I am the main content.</template>
<template slot="footer">This is the footer.</template>
</layout>
</template>
上述案例,含括了插槽的的所有基本概念:匿名插槽、具名插槽以及参数传值,参数传值的实际应用后面会具体分析。解析后的内容会按照header
,default
,footer
的顺序依次展示。可见组件中footer
、header
展示的位置是由子组件自己定义的,但是展示的具体内容,则是由父组件进行设置并传递到子组件。
实战应用
实战应用一:element UI
组件解析
实战应用,我们一起来分析一下element UI
中的Table
组件。Table
的Table Column
提供了两个插槽供用户使用,分别是:
- default 自定义列的内容,参数为 { row, column, $index }
- header 自定义表头的内容. 参数为 { column, $index }
虽然不清楚他内部是如何实现的,但是根据组件的使用可以了解到,他默认提供了一个Table 表头以及列内容的展示,通过添加header
或者 default
来替换之前已有的表头或者列内容。
来看一下实际使用并结合起来进行分析:
<template>
<el-table
:data="tableData"
style="width: 100%"
max-height="250">
<el-table-column
prop="zip"
label="邮编"
width="120">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="120">
<template v-slot="scope">
<el-button
@click.native.prevent="deleteRow(scope.$index, tableData)"
type="text"
size="small">
移除
</el-button>
</template>
</el-table-column>
</el-table>
</template>
这里在使用Table
组件时,默认他会根据prop
来逐行读取 tableData
中的数据。正常情况下,这里如果添加一个是无法读取到传递给当前Table column
的行内容的,通过给 Table column
添加 slot-scope
来完成default
插槽的替换,来完成自定义内容,上述代码完成了根据当前行的索引值完成当前行内容的删除功能。
实战应用二:项目组件封装
项目在实际过程中,往往需要对element UI
等开源组件进行二次封装,比如现在要求实现一个动态展示Table
信息的组件,要求读取type
属性来展示不同组件,且可以读取数组长度完成完整内容的展示。
首先分析,需求不是很复杂,通过参照实战应用一,添加v-for
循环,动态读取配置参数,然后在默认插槽中完成内容的判断以及展示。
<fks-table>
<fks-table-column
v-for="(item, index) in tableColumnTemp"
:key="index">
<template v-slot="slotProps">
<slot :name="item.prop" :dataRow="slotProps.row">
<time-picker v-if></time-picker>
<input v-else-if/>
<... v-else-if></...>
<component v-else></component>
</slot>
</template>
</fks-table-column>
</fks-table>
通过上述分析,可以看到实现起来也是很简单的,值得注意的是,在中还添加了一层绑定了name属性的具名插槽,这里是提供给了组件调用的用户更佳的灵活性,通过对应到相关的具名插槽,可以重写组件默认实现的内容。
说到最后
怎么样,看了文章之后,是不是觉得对插槽的理解更加深入了呢?插槽,尤其是在组件封装中,可谓是一支奇兵,为我们组件的封装提供了更多便捷,赶快用起来吧!