在封装组件的过程中,可以为预留的
插槽绑定 props
数据,这种带有 props 数据的
叫做作用域插槽。通过作用域插槽,把组件数据返回给,组件调用方。
<template>
<div>
<h3>这是 TEST 组件h3>
<slot :info="infomation" :msg="message">slot>
div>
template>
<script>
export default {
name: 'MyTest',
data() {
return {
// 信息数据
infomation: {
phone: '138xxxx6666',
address: '中国北京',
},
message: 'abc'
}
},
}
script>
组件调用者
<template>
<div>
<h1>App 根组件h1>
<hr />
<my-test>
<template #default="{ msg, info }">
<p>{{ msg }}p>
<p>{{ info.address }}p>
template>
my-test>
<hr />
<my-table>
<template #default="{ user }">
<td>{{ user.id }}td>
<td>{{ user.name }}td>
<td>
<input type="checkbox" :checked="user.state" />
td>
template>
my-table>
div>
template>
<script>
// 导入组件
import MyTest from './MyTest.vue'
export default {
name: 'MyApp',
// 注册组件
components: {
MyTest,
},
}
script>
通过
作用域插槽返回用户数据给组件调用者,进行自定义渲染。
<template>
<table class="table table-bordered table-striped table-dark table-hover">
<thead>
<tr>
<th>Idth>
<th>Nameth>
<th>Stateth>
tr>
thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<slot :user="item">slot>
tr>
tbody>
table>
template>
<script>
export default {
name: 'MyTable',
data() {
return {
// 列表的数据
list: [
{ id: 1, name: '张三', state: true },
{ id: 2, name: '李四', state: false },
{ id: 3, name: '赵六', state: false },
],
}
},
}
script>
组件调用者
<template>
<div>
<h1>App 根组件h1>
<hr />
<my-table>
<template #default="{ user }">
<td>{{ user.id }}td>
<td>{{ user.name }}td>
<td>
<input type="checkbox" :checked="user.state" />
td>
template>
my-table>
div>
template>
<script>
// 导入组件
import MyTable from './MyTable.vue'
export default {
name: 'MyApp',
// 注册组件
components: {
MyTable,
},
}
script>
data
的prop
属性,为 MyTable.vue
组件指定数据源MyTable.vue
组件中,预留名称为 header
的具名插槽MyTable.vue
组件中,预留名称为 body
的作用域插槽MyTable.vue
组件<template>
<table class="table table-bordered table-striped">
<thead>
<tr>
<slot name="header">slot>
tr>
thead>
<tbody>
<tr v-for="(item, index) in data" :key="item.id">
<slot name="body" :row="item" :index="index">slot>
tr>
tbody>
table>
template>
<script>
export default {
name: 'MyTable',
props: {
data: {
type: Array,
required: true,
default: []
}
}
}
script>
<style lang="less" scoped>style>
<template>
<div>
<h1>App 根组件h1>
<hr />
<my-table :data="goodslist">
<template v-slot:header>
<th>序号th>
<th>商品名称th>
<th>价格th>
<th>标签th>
<th>操作th>
template>
<template v-slot:body="{ row, index }">
<td>{{ index + 1 }}td>
<td>{{ row.goods_name }}td>
<td>¥{{ row.goods_price }}td>
<td>
<input
type="text"
class="form-control form-control-sm form-ipt"
v-if="row.inputVisible"
v-focus
v-model.trim="row.inputValue"
@blur="onInputConfirm(row)"
@keyup.enter="onInputConfirm(row)"
@keyup.esc="row.inputValue = ''"
/>
<button type="button" class="btn btn-primary btn-sm" v-else @click="row.inputVisible = true">+Tagbutton>
<span class="badge badge-warning ml-2" v-for="item in row.tags" :key="item">{{ item }}span>
td>
<td>
<button type="button" class="btn btn-danger btn-sm" @click="onRemove(row.id)">删除button>
td>
template>
my-table>
div>
template>
<script>
import MyTable from './components/my-table/MyTable.vue'
export default {
name: 'MyApp',
data() {
return {
// 商品列表的数据
goodslist: [],
}
},
created() {
// 发起请求
this.getGoodsList()
},
methods: {
// 请求商品列表的数据
async getGoodsList() {
const { data: res } = await this.$http.get('/api/goods')
if (res.status !== 0) return console.log('获取商品列表数据失败!')
this.goodslist = res.data
},
// 根据 Id 删除商品
onRemove(id) {
this.goodslist = this.goodslist.filter(x => x.id !== id)
},
onInputConfirm(row) {
const val = row.inputValue
row.inputValue = ''
row.inputVisible = false
if (!val || row.tags.indexOf(val) !== -1) return
row.tags.push(val)
},
},
directives: {
focus(el) {
el.focus()
},
},
components: {
MyTable,
},
}
script>
<style lang="less" scoped>
.form-ipt {
width: 80px;
display: inline;
}
style>