Vue3 作用域插槽
在封装组件的过程中,可以为预留的 <slot>
插槽绑定 props 数据,这种带有 props 数据的
MyTest组件
<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>
<!-- 直接解构组件MyTest 返回的数据-->
<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>
MyTable组件
通过<slot :user="item"></slot>
作用域插槽返回用户数据给组件调用者,进行自定义渲染。
<template>
<table class="table table-bordered table-striped table-dark table-hover">
<!-- 表头区域 -->
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>State</th>
</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>
封装 MyTable
-
用户通过名为 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">
<!-- 作用域插槽返回 row index -->
<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>
<!-- 接收作用域插槽返回的 row index ,自定义渲染-->
<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">+Tag</button>
<!-- 循环渲染标签信息 -->
<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>
————————————————
版权声明:本文为CSDN博主「DevCsdner」的原创文章
原文链接:https://blog.csdn.net/smartboy_01/article/details/126943969
原文始发于微信公众号(前端24):Vue3 作用域插槽
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/253945.html