vite + vue3 + ts 搭建一套自己的后台管理系统 (4)

871 阅读3分钟

前言

本来这篇准备看下 element ui 源码自己实现一个简易版的 el-table,但是发现 el-table-column 的实现有点没搞明白,那后面再详细看下实现方案,争取下个月的文档更新出来。这篇实现一个表格的条件查询组件。

场景

多数的后台管理系统都是表格的数据,业务逻辑也无非就是增删改查。我们来看下这个查询的页面

image.png

如果搜索条件比较多的话,我们每个页面都要写很多个输入框,每个页面都是复制粘贴,就会显得比较乱。那我们就可以考虑把这个组件封装一下,根据我们传递的数据来渲染不同的表单类型。

实现思路

我们需要接收一个数组,数组中存放不同的输入类型,根据不同的类型渲染对应的输入框

<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 属性来和对象中对应,同时接收传入的对象,生成响应式数据

image.png

暴露出实例化方法来获取输入框更新的数据,父组件调用该方法时可以获取到最新的值

const getFormValues = ()=>{
    return new Promise(resolve=>{
        resolve(params.value)
    })
}
defineExpose({getFormValues})

父组件中

image.png

此时一个简单的功能已经实现,我们来完善一下数据中传入的数据,比如label,placeholder等根据自己实际需求添加配置。

自定义输入框

比如我们定义的输入框类型是我们组件中没有的,我们需要自己自定义,我们可以通过作用插槽方式,在父组件中进行修改。插槽不了解的小伙伴可以看我之前的文章 juejin.cn/post/720709…

image.png

根据我们自己的需求进行修改 image.png

image.png

同样的方式,我们也可以把查询按钮也封装进来。有兴趣的小伙伴可以自己尝试。简易的代码贴一下,根据自己项目的需要可以进行完善。 子组件

<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>

最后

又是月底了才匆匆忙忙地结尾,拖延症太严重了,下个月尽量早点完工。双节快乐!