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>
- 复制代码