前言
本来这篇准备看下 element ui 源码自己实现一个简易版的 el-table,但是发现 el-table-column 的实现有点没搞明白,那后面再详细看下实现方案,争取下个月的文档更新出来。这篇实现一个表格的条件查询组件。
场景
多数的后台管理系统都是表格的数据,业务逻辑也无非就是增删改查。我们来看下这个查询的页面
如果搜索条件比较多的话,我们每个页面都要写很多个输入框,每个页面都是复制粘贴,就会显得比较乱。那我们就可以考虑把这个组件封装一下,根据我们传递的数据来渲染不同的表单类型。
实现思路
我们需要接收一个数组,数组中存放不同的输入类型,根据不同的类型渲染对应的输入框
<template>
<el-form :inline="true">
<el-form-item label="姓名" v-for="item in formData" :key="item.id">
<el-input v-if="item.type=='input'" v-model="formParams.name" style="width:220px ;"></el-input>
<el-select v-if="item.type=='select'" v-model="formParams.name" style="width:220px ;">
<el-option
v-for="item in item.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
</template>
<script setup>
const props=defineProps({
formData:{
type:Array,
default:[
{
id:1,
type:'input',
value:''
},
{
id:2,
type:'select',
value:'',
options:[
{
value:0,
label:'无业游民'
},
{
value:1,
label:'自由职业'
},
{
value:2,
label:'要饭程序员'
}
]
}
]
},
formParams:{
type:Object,
default:{
name
}
}
})
</script>
此时页面已经被渲染出来,但此时v-model绑定的数据是有问题的,因为这里是动态传入,不能定死。我们定义表单通常会采用对象包裹方式来使用。我们定义一个对象传入,同时还需要和这个数组有关联,不然我们无法确定绑定的是哪个对象属性。
我们在数组中定义value 属性来和对象中对应,同时接收传入的对象,生成响应式数据
暴露出实例化方法来获取输入框更新的数据,父组件调用该方法时可以获取到最新的值
const getFormValues = ()=>{
return new Promise(resolve=>{
resolve(params.value)
})
}
defineExpose({getFormValues})
父组件中
此时一个简单的功能已经实现,我们来完善一下数据中传入的数据,比如label,placeholder等根据自己实际需求添加配置。
自定义输入框
比如我们定义的输入框类型是我们组件中没有的,我们需要自己自定义,我们可以通过作用插槽方式,在父组件中进行修改。插槽不了解的小伙伴可以看我之前的文章 juejin.cn/post/720709…
根据我们自己的需求进行修改
同样的方式,我们也可以把查询按钮也封装进来。有兴趣的小伙伴可以自己尝试。简易的代码贴一下,根据自己项目的需要可以进行完善。
子组件
<template>
<el-form :inline="true" :model="params">
<el-form-item :label="item.label" v-for="item in formData" :key="item.id">
<slot name="form" :row="item" :data="params">
<el-input v-if="item.type=='input'" v-model="params[item.value]" style="width:220px ;"></el-input>
<el-select v-if="item.type=='select'" v-model="params[item.value]" style="width:220px ;">
<el-option
v-for="item in item.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker v-if="item.type=='date'"
v-model="params[item.value]"
type="date"
/>
</slot>
</el-form-item>
</el-form>
</template>
<script setup>
import {ref} from "vue"
const props=defineProps({
formData:{
type:Array,
default:()=>[]
},
formParams:{
type:Object,
default:()=>{}
}
})
const params=ref(props.formParams)
const getFormValues = ()=>{
return new Promise(resolve=>{
resolve(params.value)
})
}
defineExpose({getFormValues})
</script>
父组件
<template>
<div style="padding:20px ;">
<myTableQuery :form-params="params" :form-data="formData" ref="myTableQueryRef">
<template #form="{row,params}">
<div v-if="row.value=='id'">
自定义下拉框
</div>
</template>
</myTableQuery>
<el-button type="primary" @click="getValues">获取数据</el-button>
</div>
</template>
<script lang="ts" setup>
import {ref} from "vue"
import myTableQuery from "../components/my-table-query.vue";
const params={
name:'张三',
id:0,
date:''
}
const formData=[
{
id:1,
type:'input',
value:'name',
label:'姓名'
},
{
id:2,
type:'select',
value:'id',
label:'职业',
options:[
{
value:0,
label:'无业游民'
},
{
value:1,
label:'自由职业'
},
{
value:2,
label:'要饭程序员'
}
]
},
{
id:3,
type:'date',
value:'date',
label:'时间'
},
]
const myTableQueryRef=ref()
const getValues=()=>{
myTableQueryRef.value?.getFormValues().then(res=>{
console.log(res)
})
}
</script>
最后
又是月底了才匆匆忙忙地结尾,拖延症太严重了,下个月尽量早点完工。双节快乐!