目录
一、组件插槽
组件的最大特性就是 复用性 ,而用好插槽能大大提高组件的可复用能力
1.1、单个插槽
当子组件模板只有一个没有属性的插槽时,父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,并 替换 掉插槽标签本身。
2.2、具名插槽
有时我们需要多个插槽,来完成对应的数据自定义显示。
一个不带 name 的 <slot> 出口会带有隐含的名字 “default” 。
自 2.6.0 起有所更新。已废弃的使用 slot
# 子组件
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
</div>
# 父组件
<app-layout>
// 老写法
<h1 slot="header">这里可能是一个页面标题</h1>
// 新写法
// v-slot 只能添加在 <template> 上
// 简写 v-slot:header == #header
<template v-slot:header>
<h1>这里可能是一个页面标题</h1>
</template>
<p>主要内容的一个段落。</p>
</app-layout>
2.3、作用域插槽
作用域插槽 是一种特殊类型的插槽,用作一个 (能被传递数据的) 可重用模板,来代替已经渲染好的元素。在子组件中,只需将数据传递到插槽,就像你将 prop 传递给组件一样
<div id="app">
<child :users='users'>
<!--
vue2.6之前
-->
<!-- <h6 slot="action" slot-scope="row" @click="pdel(row)">删除一下</h6> -->
<!--
vue2.6之后
-->
<!-- <template v-slot:action="row">
<h3 @click="pdel(row)">删除</h3>
</template> -->
<template #action="row">
<h3 @click="pdel(row)">删除</h3>
</template>
</child>
</div>
<script type="text/template" id="userhtml">
<div>
<table width="600" border="1">
<tr>
<th>ID</th>
<th>姓名</th>
<th>操作</th>
</tr>
<tr v-for="(item,index) in users" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>
<!-- 通过slot传数据,此slot为作用域插槽 -->
<slot name="action" :info="item">
<button @click="del(index)">删除</button>
</slot>
</td>
</tr>
</table>
</div>
</script>
<script>
const child = {
props: ['users'],
name: 'child',
template: '#userhtml',
methods: {
del(index) {
console.log(index)
}
}
}
const vm = new Vue({
el: '#app',
data() {
return {
users: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
]
}
},
components: { child },
methods: {
pdel(row) {
console.log(row.info)
}
}
})
</script>
自己项目中的使用 , 仅供参考 :
比如我这里有很多页面的头部都一样,所以这里我们可以利用插槽的复用性来进行一下代码的简化 :
<template>
<div>
<div class="header">
<img src="../assets/image/LOGO.png">
</div>
<!--具名插槽-->
<slot name="content"></slot>
</div>
</div>
</template>
<script>
export default {}
</script>
使用 :
<template>
<div id="dwBodyUser">
<public-header>
<el-tabs
v-model="activeName"
@tab-click="handleClick"
slot="content"
>
<el-tab-pane
label="所有事项"
name="first"
:model="formData"
ref="formDatas"
>
<!-- 所有事项组件 -->
<all-matters></all-matters>
</el-tab-pane>
<el-tab-pane
label="场景共享"
name="second"
:model="formData"
ref="formDatas"
>
<!-- 场景共享组件 -->
<scene-sharing></scene-sharing>
</el-tab-pane>
</el-tabs>
</public-header>
</div>
</template>
<script>
import publicHeader from '@/components/publicHeader/index.vue'
import allMatters from './component/allMattersTab.vue'
import screnSharing from './component/sceneSharingTab.vue'
export default {
components: {
publicHeader, // 公共头部组件
allMatters, // 所有事项组件
sceneSharing, // 场景共享组件
}
}
</script>
还有一个 公共 Table 示例 :
<!--作者 : 小灰狼
功能 : 表格组件
时间 : 2022/01-->
<template>
<div>
<el-table :data="tableList" style="width: 100%" :header-cell-style="{background: '#EFEFEF'}">
<el-table-column type="selection" width="55" v-if="showCheckBox"></el-table-column>
<el-table-column label="序号" width="120" v-if="showNumber">
<template slot-scope="scope">{{ scope.$index + 1 }}</template>
</el-table-column>
<el-table-column v-for="item in headerList" :prop="item.props" :label="item.label" :min-width="item.minWidth"></el-table-column>
<el-table-column fixed="right" label="操作" width="300">
<template slot-scope="scope">
<el-popconfirm title="是否确定?">
<el-button slot="reference" style="color:#ED3740">{{ content }}</el-button>
</el-popconfirm>
</template>
<!-- 事项操作插槽 -->
<slot name="matterOperation"></slot>
<!-- 场景操作插槽 -->
<slot name="sceneOperation"></slot>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
props: {
tableList: {
type: Array
},
headerList: {
type: Array
},
showCheckBox: { // 是否显示多选框
type: Boolean,
default: false
},
showNumber: { // 是否显示序号
type: Boolean,
default: true
},
content: {
type: String,
default: "删除"
},
}
}
</script>
<style lang="scss" scoped>
.cell button {
border: none;
padding-left: 0
}
</style>
使用 :
<template>
<div>
<public-table
:tableList="tableList"
:showNumber="formData.showNumber"
:headerList="headerList"
>
<!-- 场景操作插槽 -->
<template #sceneOperation>
<el-tooltip content="占位">
<el-button
size="small"
icon="el-icon-edit-outline"
></el-button>
</el-tooltip>
</template>
</public-table>
</div>
</template>
<script>
import publicTable from '@/components/publicTable/index'
export default {
components: {
publicTable, // 公共表格组件
}
}
</script>