【Vue2】PaginationSelect 带分页和搜索功能的下拉列表组件

1. 效果图

【Vue2】PaginationSelect 带分页和搜索功能的下拉列表组件_第1张图片

2. 组件完整代码

<template>
    <div class="pagination-select">
        <el-select
            v-model="selectedValue"
            :style="{ width: width || '100%' }"
            v-bind="attrs"
            :remote-method="remoteMethod"
            :loading="loading"
            @change="val => $emit('change', val)"
            @clear="onClear"
            @visible-change="val => $emit('visible-change', val)"
            :disabled="disabled"
        >
            <el-option v-for="item in optionSource" :key="item[keyValue]" :label="item[labelKey]" :value="item[valueKey]">el-option>
            <el-pagination
                small
                layout="prev, pager, next"
                @current-change="val => pageChange(val)"
                :hide-on-single-page="false"
                :page-size="paginationOption.pageSize"
                :current-page="paginationOption.pageNum"
                :pager-count="pagerCount"
                :total="paginationOption.total"
            >el-pagination>
        el-select>
    div>
template>

<script>
export default {
    name: 'PaginationSelect',
    props: {
        value: {
            type: [String, Number, Object]
        },
        // 选择框宽度
        width: {
            type: String
        },
        // 下拉列表加载状态
        loading: {
            type: Boolean,
            default: false
        },
        // 传入的option数组中,要作为最终选择项的键值名称
        valueKey: {
            type: String,
            default: ''
        },
        //传入的option数组中,要作为显示项的键值名称
        labelKey: {
            type: String,
            default: ''
        },
        // 传入的option数组中,要作为显示项的key值
        keyValue: {
            type: String,
            default: ''
        },
        // 下拉框组件数据源
        optionSource: {
            type: Array,
            default: () => []
        },
        // 下拉框是否禁用
        disabled: {
            type: Boolean,
            default: false
        },
        // 按钮数,超过时会折叠
        pagerCount: {
            type: Number,
            default: 5
        },
        // 分页配置项
        paginationOption: {
            type: Object,
            default: () => {
                return {
                    pageNum: 1, // 当前页
                    pageSize: this.$store.state.app.pageSize, // 每页显示条数:默认20条
                    total: 0, // 总页数
                    keyword: ''
                }
            }
        }
    },
    computed: {
        selectedValue: {
            get() {
                return this.value
            },
            set(val) {
                this.$emit('input', val)
            }
        },
        attrs() {
            return {
                'popper-append-to-body': false,
                clearable: true,
                filterable: true,
                remote: true,
                ...this.$attrs
            }
        }
    },
    watch: {
        selectedValue(val) {
            this.selectedValue = val
        }
    },
    methods: {
        // 页码改变函数
        pageChange(val) {
            this.$emit('page-change', {
                pageNum: val,
                pageSize: this.paginationOption.pageSize,
                total: this.paginationOption.total,
                keyword: this.paginationOption.keyword
            })
        },
        // 远程搜索
        remoteMethod(query) {
            this.$emit('remote-method', {
                pageNum: 1,
                pageSize: this.paginationOption.pageSize,
                total: this.paginationOption.total,
                keyword: query
            })
        },
        onClear() {
            this.$emit('clear')
        }
    }
}
script>

<style scoped lang="less">
.pagination-select {
    ::v-deep .el-pagination {
        display: flex;
        margin-top: 10px;
        margin-left: 16px;
        background-color: #fff;
        align-items: center;
        text-align: center;
        .el-pager {
            display: flex;
            align-items: center;
        }
    }
}
style>

3. 组件使用示例

<el-form-item label="学校" prop="schoolNo">
    <PaginationSelect
        :loading="schoolLoading"
        width="360px"
        v-model="ruleForm.schoolNo"
        :optionSource="schoolOptions"
        labelKey="schoolName"
        valueKey="schoolNo"
        keyValue="schoolNo"
        :paginationOption="schoolPagination"
        @page-change="getSchoolList"
        @remote-method="getSchoolList"
        @visible-change="schoolNoFocus"
        @clear="handleClear()"
        :loading-text="schoolOptions.length && schoolLoading ? '加载中' : '无数据'"
    />
el-form-item>
data() {
    return {
        schoolLoading: false,
        schoolOptions: [],
        schoolPagination: {
            pageNum: 1,
            pageSize: 10,
            total: 0,
            keyword: ''
        }
    }
},
methods: {
    // 弹窗初始化
    init(row) {
        this.dialogVisible = true
        this.getDetail(row.id)
        // 回显学校名称
        this.schoolOptions = [
            {
                schoolNo: row.schoolNo,
                schoolName: row.schoolName
            }
        ]
    },
    // 获取详情
    getDetail(id) {
        getClockEnrollCollectDetail({
            clockEnrollCollectId: id
        })
            .then(res => {
                this.ruleForm = res.data.data
            })
            .catch(err => {})
    },
    // 获取学校下拉
    getSchoolList(val) {
        this.schoolOptions = []
        this.schoolLoading = true
        enrollSchoolPage({
            pageNum: val.pageNum,
            pageSize: val.pageSize,
            nameOrNo: val.keyword || ''
        })
            .then(res => {
                this.schoolLoading = false
                if (res.data.data.records.length) {
                    this.schoolOptions = res.data.data.records || []
                    // 更新页码数据
                    this.schoolPagination = {
                        pageNum: val.pageNum,
                        pageSize: val.pageSize,
                        keyword: val.keyword || '',
                        total: res.data.data.total
                    }
                }
            })
            .catch(err => {
                this.schoolLoading = false
            })
    },
    // 学校下拉框出现/隐藏
    schoolNoFocus(val) {
        if (val) {
            this.getSchoolList(this.schoolPagination)
        } else {
            this.schoolPagination.pageNum = 1
            this.schoolPagination.keyword = ''
            this.schoolPagination.total = 0
        }
    },
    // 清空分页下拉列表选中的值重置下拉列表数据
    handleClear() {
        this.schoolPagination.pageNum = 1
        this.schoolPagination.keyword = ''
        this.schoolPagination.total = 0
        this.ruleForm.schoolNo = ''
        this.ruleForm.schoolName = ''
    }
}

你可能感兴趣的:(自定义组件,前端,vue.js)