vue + element 实现的可配置的数据搜索组件

vue + element 实现的可配置的数据搜索组件(搜索框 + table展示 + 分页控制)

说明:

在管理系统中,涉及到很多根据查询条件,查出数据,然后使用表格展示的页面。

对于这种复用性极强的page,提供一个公共的组件是很必要的(样式统一、高效开发)。

主要切分为3个组件。

1、Filter 功能:搜索条件,搜索按钮

2、Table 功能:展示数据,列表内实现一些操作如:查看、编辑等

3、Pagination 功能:分页,控制页面大小,页面数

调用方式:

<template lang="pug">
FilterTable(
    :list="list"
    :filters="filters"
    :tableList="tableList"
    :pageNum="pageNum"
    :pageSize="pageSize"
    :total="total"
    @listenHandleClickFilterButton="handleClickFilterButton"
    @listenHandleClickTableColumnHref="handleClickTableColumnHref"
    @listenHandleChangePaginationSize="handleChangePaginationSize"
    @listenHandleChangePaginationNum="handleChangePaginationNum"
) 
</template>
import FilterTable from '@/components/common/c-filter-table'
import list from './list'
export default {
    components: {
        FilterTable
    },
    created() {},
    data() {
        return {
            pageNum: 1,
            pageSize: 20,
            total: 0,
            tableList: [],
            list,
            filters: list.filterList.reduce((obj, item) => {
                if (item.type !== 'button') {
                    obj[item.key] = ''
                }
                return obj
            }, {}),
        }
    },
    methods: {
        handleClickFilterButton(buttonKey) {
            if (buttonKey === 'search') {
                this.handleClickSearch()
            }
            if (buttonKey === 'reset') {
                this.handleClickReset()
            }
            if (buttonKey === 'export') {
                this.handleClickExport()
            }
            if (buttonKey === 'add') {
                this.handleClickAdd()
            }
        },
        handleClickTableColumnHref(columnKey, row) {
            if (columnKey === 'edit') {
                console.log('click column edit')
            }
        },
        handleChangePaginationSize(size) {
            this.pageNum = 1
            this.pageSize = size
            this.handleClickSearch()
        },
        handleChangePaginationNum(num) {
            this.pageNum = num
            this.handleClickSearch()
        },
        async handleClickSearch() {
            ...
        },
        handleClickAdd() {
            ...
        },
        async handleClickReset() {
            this.filters = list.filterList.reduce((obj, item) => {
                if (item.type !== 'button') {
                    obj[item.key] = ''
                }
                return obj
            }, {})

            ...
        }
    }
}
        
复制代码

参数说明

list:搜索框配置、表格字段配置

一个list配置如下:

const list = {
    filterList: [
        {
            label: '座位号',
            key: 'id',
            type: 'input',
            span: 6
        },
        {
            label: '班级',
            key: 'class',
            type: 'select',
            options: [
                {
                    key: '1',
                    label: '一班',
                    val: '1'
                },
                {
                    key: '2',
                    label: '二班',
                    val: '2'
                }
            ],
            span: 6
        },
        {
            label: '入学日期',
            key: 'statPeriod',
            type: 'datePicker',
            span: 6,
            config: {
                type: 'date',
                placeholder: '选择日期'
            }
        },
        {
            label: '入校时长',
            key: 'backDate',
            type: 'datePicker',
            config: {
                type: 'daterange',
                rangeSeparator: '至',
                startPlaceholder: '开始日期',
                endPlaceholder: '结束日期'
            },
            span: 12
        },
        {
            label: '查询',
            key: 'search',
            type: 'button',
            config: {
                type: 'primary'
            },
            span: 2
        },
        {
            label: '重置',
            key: 'reset',
            type: 'button',
            config: {
                type: ''
            },
            span: 2
        },
        {
            label: '导出',
            key: 'export',
            type: 'button',
            config: {
                type: 'success'
            },
            span: 2
        }
    ],
    tableColumns: [
        {
            label: '状态',
            key: 'stateName'
        },
        {
            label: '编号',
            key: 'code'
        },
        {
            label: '姓名',
            key: 'name'
        },
        {
            label: '年龄',
            key: 'remark'
        },
        {
            label: '操作',
            key: 'edit',
            type: 'href',
            filter: () => '编辑'
        }
    ],
复制代码

filterList 用于配置搜索框 对应的事件处理为:listenHandleClickFilterButton

tableColumns 用于配置表格字段 对应的事件处理为:listenHandleClickTableColumnHref

tableList: 搜索结果,传入table的数据

pageNum、pageSize、total: 分页需要的数据

对应的控制分页事件为:listenHandleChangePaginationSize、listenHandleChangePaginationNum

c-filter-table完整代码:

<template lang="pug">
.c-table-container       
    el-form.search-box
        el-row(:gutter="20")
            template(v-for="item in list.filterList")
                el-col(
                    v-if="item.type==='button'"
                    :span="item.span"
                    :key="item.key")
                    el-button(:type="item.config.type" @click="handleClickFilterButton(item.key)") {{ item.label }}
                el-col(
                    v-else
                    :span="item.span"
                    :key="item.key")
                    el-form-item(
                        :label="item.label"
                        :prop="item.key"
                        label-width="110px")
                        el-input(
                            v-if="item.type==='input'"
                            v-model="filters[item.key]")
                        el-select(
                            v-if="item.type==='select'"
                            v-model="filters[item.key]")
                            el-option(
                                v-for="option in item.options" 
                                :key="option.key" 
                                :value="option.val" 
                                :label="option.label")
                        el-select(
                            v-if="item.type==='select-filterable'"
                            v-model="filters[item.key]"
                            filterable placeholder="请选择")
                            el-option(
                                v-for="option in item.options" 
                                :key="option.key" 
                                :value="option.val" 
                                :label="option.label")
                        el-date-picker(
                            v-if="item.type==='datePicker'"
                            v-model="filters[item.key]"
                            :type="item.config.type"
                            :range-separator="item.config.rangeSeparator"
                            :start-placeholder="item.config.startPlaceholder"
                            :end-placeholder="item.config.endPlaceholder")

    el-table(:data="tableList" border)
        el-table-column(
            type="index"
            label="序号"
            align="center")
        el-table-column(
            v-for="item in list.tableColumns" 
            :key="item.key"
            :label="item.label"
            :prop="item.key"
            align="center")
            template(slot-scope="scope")  
                a(
                    v-if="item.type === 'href'"
                    class="blue"
                    @click="handleClickTableColumnHref(item.key, scope.row)"
                ) {{ item.filter(scope.row) }}
                
                span(v-else) {{ item.filter ? item.filter(scope.row) : scope.row[item.key] }}
    el-pagination(
        @size-change="handleChangePaginationSize"
        @current-change="handleChangePaginationNum"
        :page-sizes="[10, 20, 50, 100]"
        :current-page.sync="selfPageNum"
        :page-size="selfPageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total")
</template>

<script>
export default {
    props: [
        'list',
        'tableList',
        'total',
        'pageNum',
        'pageSize',
        'filters',
        'listenHandleClickFilterButton',
        'listenHandleClickTableColumnHref',
        'listenHandleChangePaginationSize',
        'listenHandleChangePaginationNum'
    ],
    data() {
        return {
            selfPageNum: this.pageNum,
            selfPageSize: this.pageSize
        }
    },
    methods: {
        handleClickFilterButton(filterKey) {
            this.$emit('listenHandleClickFilterButton', filterKey)
        },
        handleClickTableColumnHref(columnKey, row) {
            this.$emit('listenHandleClickTableColumnHref', columnKey, row)
        },
        handleChangePaginationSize(val) {
            this.selfPageNum = 1
            this.selfPageSize = val
            this.$emit('listenHandleChangePaginationSize', val)
        },
        handleChangePaginationNum(val) {
            this.selfPageNum = val
            this.$emit('listenHandleChangePaginationNum', val)
        }
    }
}
</script>

<style scoped lang="scss">
.el-row {
    margin-bottom: 20px;
    &:last-child {
        margin-bottom: 0;
    }
}
.el-col {
    border-radius: 4px;
}
.blue {
    color: #409eff;
}
.c-table-container {
    padding: 15px;
    min-height: 500px;
    .search-box.el-form {
        display: flex;
        flex-wrap: wrap;
        .el-form-item {
            .el-input {
                width: 160px;
            }
        }
    }
    .extand {
        .el-form-item {
            width: 25%;
        }
    }
    .el-pagination {
        text-align: right;
        padding: 10px;
    }
}
</style>
复制代码

转载于:https://juejin.im/post/5c909c995188252dac6d292b

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值