- 作者:老汪软件技巧
- 发表时间:2024-10-02 00:02
- 浏览量:
封装一个UI库,加点自己的东东,是不是就可以变成自己的UI库呢?
好吧这不是重点,重点是封装之后呢,遇到的一个问题就是,原来UI库自带的插槽怎么透露出来?总不能一个一个定义吧。其实不难,只需要一个 v-for 就可以搞定。
普通插槽
以 el-input 为例来看看如何透传。
封装一下 el-input
做一个组件 my-input.vue
<template>
<el-input v-model="model" placeholder="">
<template
v-for="(item, key) in $slots"
v-slot:[key]
>
<slot :name=key> slot>
template>
el-input>
template>
不需要写js代码,仅仅在 template 里面 v-for 一下即可。
使用方式
先 import 组件,然后按照 el-input 的插槽设置即可:
import myInput from './slot-son.vue'
const person = reactive({
name: 'jyk'
})
按照官网的例子,设置一个 suffix 插槽:
<myInput v-model="person.name">
<template #suffix>
<el-icon class="el-input__icon"><calendar />el-icon>
template>
myInput>
当然还可以设置其他插槽,就像使用 el-input 那样。
<myInput v-model="person.name">
<template #suffix>
<el-icon class="el-input__icon"><calendar />el-icon>
template>
<template #prefix>
<el-icon class="el-input__icon"><search />el-icon>
template>
<template #prepend>Http://template>
<template #append>
<el-select v-model="person.name" placeholder="Select" style="width: 115px">
<el-option label="Restaurant" value="1" />
<el-option label="Order No." value="2" />
<el-option label="Tel" value="3" />
el-select>
template>
myInput>
作用域插槽
这个有点绕圈圈,其实只需要加了一个属性绑定即可。
封装一下 el-table
input 没有作用域插槽,所以这次我们使用 el-table 来举例:
<el-table style="width: 100%">
<el-table-column v-for="(key) in labels" :label="key" width="180">
<template v-if="$slots[key]" #default="scope">
<slot :name="key" v-bind="scope">slot>
template>
el-table-column>
el-table>
table-column 只有一个匿名插槽,也就是默认插槽,对于 column 来说这就可以了,但是封装后我们只想暴露table,所以还需要定义具名插槽,就以字段名作为插槽名称。
所以我们定义一个数组来存放字段名称,这里简化设置。
type TProps = {labels: string[]}
const props = defineProps<TProps>()
这样就完成了一个作用域插槽的透传。
使用方式
我们先定义一个字段数组,以及模拟数据:
import mytable from './slot-table.vue'
interface User {
date: string
name: string
address: string
}
const labels = [
'日期',
'name',
'address',
'Operations'
]
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom1',
address: 'No. 1, Grove St, Los Angeles',
},
...
]
然后我们先设置一个 日期 的插槽:
<mytable :data="tableData" :labels="labels">
<template #日期="scope">
<div style="display: flex; align-items: center">
<el-icon><timer />el-icon>
<span style="margin-left: 10px">{{ scope.row.date }}span>
div>
template>
mytable>
我们还可以设置其他插槽:(代码来自于官网实例)
<mytable :data="tableData" :labels="labels">
<template #日期="scope">
<div style="display: flex; align-items: center">
<el-icon><timer />el-icon>
<span style="margin-left: 10px">{{ scope.row.date }}span>
div>
template>
<template #name="scope">
<el-popover effect="light" trigger="hover" placement="top" width="auto">
<template #default>
<div>name: {{ scope.row.name }}div>
<div>address: {{ scope.row.address }}div>
template>
<template #reference>
<el-tag>{{ scope.row.name }}el-tag>
template>
el-popover>
template>
<template #address="scope">
{{ scope.row.address }}
template>
<template #Operations="scope">
<el-button size="small" @click="handleEdit(scope.$index, scope.row)">
Edit
el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>
Delete
el-button>
template>
mytable>
这样做有何意义?这是低代码的一种实现方式,借用成熟的UI库,实现基础功能,然后用JSON绑定普通的字段,最后用插槽搞定特殊的字段。
这样可以实现既方便,又灵活的效果。
和原本 el-table 有何区别?这区别可就多了。
首先这个列是由 v-for 遍历出来的,也就是说,如果想要改变列的前后顺序,那么我们不需要修改 template,只需要修改数组里的元素的先后顺序即可。
还有其他各种好处,先不说了,做过低代码的都懂。