vue + element 實現的可配置的數據搜索組件

vue + element 實現的可配置的數據搜索組件(搜索框 + table展現 + 分頁控制)

說明:css

在管理系統中,涉及到不少根據查詢條件,查出數據,而後使用表格展現的頁面。vue

對於這種複用性極強的page,提供一個公共的組件是很必要的(樣式統1、高效開發)。bash

主要切分爲3個組件。async

一、Filter 功能:搜索條件,搜索按鈕flex

二、Table 功能:展現數據,列表內實現一些操做如:查看、編輯等ui

三、Pagination 功能:分頁,控制頁面大小,頁面數this

調用方式:spa

<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配置以下:code

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 用於配置搜索框 對應的事件處理爲:listenHandleClickFilterButtoncomponent

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>
複製代碼
相關文章
相關標籤/搜索