项目需要select显示的选项太多了,添加分页方便查找。新建一个组件dropdownPagination组件,可以实现远程搜索、分页查询的功能。项目使用,记录一下,方便后续引用。
子组件代码
创建组件页面src\components\Select\index.vue
<!-- 下拉框组件 -->
<template>
<el-select
v-model="localSelectValue"
:filterable="filterable"
:multiple="multiple"
:size="selectSize"
:clearable="selectClearable"
:collapse-tags="selectCollapseTags"
:placeholder="selectPlaceholder"
:no-match-text="selectNoMatchText"
@search="handleSearch"
@clear="handleClear"
remote
:remote-method="handleSearch"
>
<el-option
v-for="item in selectOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
<div style="margin: 15px 10px">
<el-pagination
:background="background"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:pager-count="pagerCount"
:total="total"
v-bind="$attrs"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-select>
</template>
<script>
/**
* 定义组件的props,包括类型、默认值等属性。
*
* @param {Boolean} selectCollapseTags - 是否选择折叠标签,默认值为true
* @param {Boolean} selectClearable - 是否可清除选择,默认值为true
* @param {String} selectSize - 选择框的大小,默认值为"small"
* @param {Boolean} filterable - 是否可过滤,默认值为true
* @param {Boolean} multiple - 是否允许多选,默认值为false
* @param {String} selectPlaceholder - 选择框的占位符文本,默认值为"请选择"
* @param {Number} total - 必需,数据总数
* @param {Number} page - 当前页码,默认值为1
* @param {Number} limit - 每页显示条数,默认值为20
* @param {Array} pageSizes - 可选的每页显示条数数组,默认为[10, 20, 30, 50, 80, 100]
* @param {String} layout - 分页组件的布局,默认值为"total, sizes, prev, pager, next, jumper"
* @param {Boolean} background - 是否显示背景,默认值为true
* @param {Boolean} hidden - 是否隐藏组件,默认值为false
* @param {Array} selectOptions - 可选的下拉选项数组,默认为空数组[]
* @param {(String|Number)} selectValue - 当前选中的值,可以是字符串或数字,默认值为""
* @param {Number} pagerCount - 分页器显示的按钮数量,根据屏幕宽度动态调整,默认为document.body.clientWidth < 992 ? 5 : 7
*/
export default {
name: "dropdownPagination",
props: {
selectCollapseTags: {
type: Boolean,
default: true,
},
selectNoMatchText: {
type: String,
default: "该页无匹配数据",
},
selectClearable: {
type: Boolean,
default: true,
},
selectSize: {
type: String,
default: "small",
},
filterable: {
type: Boolean,
default: true,
},
multiple: {
type: Boolean,
default: false,
},
selectPlaceholder: {
type: String,
default: "请选择",
},
total: {
required: true,
type: Number,
},
page: {
type: Number,
default: 1,
},
limit: {
type: Number,
default: 20,
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50, 80, 100];
},
},
layout: {
type: String,
default: "total, sizes, prev, pager, next, jumper",
},
background: {
type: Boolean,
default: true,
},
hidden: {
type: Boolean,
default: false,
},
selectOptions: {
type: Array,
default() {
return [];
},
},
selectValue: {
type: [String, Number],
default: "",
},
pagerCount: {
type: Number,
default: () => (document.body.clientWidth < 992 ? 5 : 7),
},
},
data() {
return {
// 搜索查询
searchQuery: "",
};
},
computed: {
/**
* 获取本地选择值,并触发更新事件
* @returns {string|number} 本地选择值
* @description 本地选择值是通过计算属性 localSelectValue 获取的,它是一个 getter/setter。
* 当获取本地选择值时,它会返回 selectValue 属性。当设置本地选择值时,它通过触发 update:selectValue 事件来更新外部的 selectValue 值。
* 这样,当本地选择值发生变化时,外部的 selectValue 也会相应更新。这通常用于父子组件之间的数据同步或双向绑定场景。
*
*/
localSelectValue: {
// 获取本地选择值,并触发更新事件
get() {
// 返回 selectValue 的值
return this.selectValue;
},
// 设置本地选择值,并触发更新事件
set(val) {
// 触发 update:selectValue 事件,并传递 val 作为参数
this.$emit("update:selectValue", val);
},
},
/**
* 获取当前页码
*
* @returns {number} 当前页码
*/
currentPage: {
get() {
// 返回当前页面
return this.page;
},
set(val) {
// 触发 update:page 事件,并传递 val 作为参数
this.$emit("update:page", val);
},
},
/**
* 获取每页显示的条目数
*
* @returns {number} 每页显示的条目数
*/
pageSize: {
get() {
// 返回限制值
return this.limit;
},
set(val) {
// 触发 update:limit 事件,并传递 val 作为参数
this.$emit("update:limit", val);
},
},
},
methods: {
/**
* 处理清空事件
*/
handleClear() {
this.searchQuery = "";
this.currentPage = 1;
this.$emit("pagination", { page: 1, limit: this.pageSize, query: "" });
},
/**
* 处理分页大小改变事件
*
* @param val 每页显示的条目数
*/
handleSizeChange(val) {
// 如果当前页与每页显示条数的乘积大于总条数
if (this.currentPage * val > this.total) {
// 将当前页重置为第一页
this.currentPage = 1;
}
this.$emit("pagination", {
page: this.currentPage,
limit: val,
query: this.searchQuery,
});
},
/**
* 处理当前页码变化的方法
*
* @param {number} val - 当前页码
*/
handleCurrentChange(val) {
this.$emit("pagination", {
page: val,
limit: this.pageSize,
query: this.searchQuery,
});
},
/**
* 处理搜索事件的方法
*
* @param query 查询字符串
*/
handleSearch(query) {
// 输出查询关键字
console.log(query);
// 将查询关键字赋值给searchQuery属性
this.searchQuery = query;
// 重置当前页码为1
this.currentPage = 1;
// 触发pagination事件,传递页码、每页显示条数和查询关键字
// 触发父组件的pagination事件,传递当前页码、每页显示条数和查询关键字
this.$emit("pagination", { page: 1, limit: this.pageSize, query });
},
},
};
</script>
全局引用:
在src\main.js文件中引用
//下拉选择器+分页组件
import dropdownPagination from "@/components/Select";
// 全局组件挂载
Vue.component('dropdownPagination', dropdownPagination)
父组件使用
在需要使用的父组件页面调用子组件
<template>
<div class="container">
<el-button type="primary"
@click="handleShare">打开弹窗</el-button>
<el-dialog
title="当前设备分配用户"
:visible.sync="centerDialogVisible"
width="30%"
center>
<dropdown-pagination
v-show="userTotal > 0"
:total="userTotal"
:page.sync="userQueryParams.pageNum"
:limit.sync="userQueryParams.pageSize"
:selectValue.sync="selectValue"
:selectOptions="selectOptionsUser"
:selectPlaceholder="'请选择用户'"
:pageSizes="[5, 10, 20, 30, 50]"
@pagination="fetchUserList"
/>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleShareSub">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { listUser } from "@/api/system/user";
export default {
data() {
return {
centerDialogVisible: false, //居中弹框
selectValue: "", //选择的用户名
userTotal: 0, //用户总数
userQueryParams: {
pageNum: 1,
pageSize: 10,
},
selectOptionsUser: [], //用户列表
},
methods: {
handleShare(row) {
this.centerDialogVisible = true; //居中弹框打开
this.fetchUserList(); //获取用户列表数据
},
/**
* 获取用户列表
*
* 从后端获取用户列表数据,并更新组件的状态
*/
fetchUserList({ page, limit, query } = {}) {
console.log(page, limit, query);//输出子组件传回的参数信息
const params = {
pageNum: page || this.userQueryParams.pageNum || 1,// 分页数,默认为1
pageSize: limit || this.userQueryParams.pageSize || 10,//每页数量,默认为10
userName: query || undefined,// 用户名查询条件,默认为undefined
};
//调用获取用户列表的API
listUser(params).then((res) => {
// 设置用户总数
this.userTotal = res.total;
// 设置用户选择框的选项
this.selectOptionsUser = res.rows.map((item) => ({
label: item.nickName,// 显示名称
value: item.nickName,// 值
}));
});
},
};
</script>
效果图: