当前位置: 首页 > news >正文

【前端开发】Uniapp分页器:新增输入框跳转功能

  • 基于 UniApp 官方扩展组件库 uni-ui 中的 uni-pagination 分页器组件,针对大数据量场景进行优化

在这里插入图片描述

  • 主要优化以下内容:
  • 新增输入框跳转功能:在原有分页器基础上,新增了一个输入框区域,允许用户直接输入目标页码进行跳转
  • 双向页码绑定优化:实现了输入框与当前页码的双向绑定机制。当用户通过其他方式(如点击上一页、下一页、页码按钮)切换页面时,输入框会自动更新显示当前页码。同时,当用户在输入框中输入页码并确认跳转时,页面也会相应更新
  • 类型安全和用户体验优化:对输入处理进行了严格的类型安全检查,且支持空值输入
    在这里插入图片描述

输入框跳转区域

  • 允许用户直接输入页码进行跳转
  • 输入限制: 只能输入数字,最大长度根据总页数确定
<view class="uni-pagination__jump"><text class="uni-pagination__jump-text">前往</text><input class="uni-pagination__jump-input" type="number" :value="jumpPage" @input="onJumpInput"@blur="onJumpBlur"@confirm="onJumpConfirm":placeholder="'1-' + maxPage":maxlength="String(maxPage).length" /><text class="uni-pagination__jump-text"></text>
</view>

输入框跳转方法

onJumpInput(e) {const value = e.detail.value;// 允许输入框为空,如果为空则设置为空字符串,否则转换为数字this.jumpPage = value === '' ? '' : Number(value) || 1;
},onJumpBlur() {// 如果输入框为空,不进行验证,保持为空if (this.jumpPage === '') {return;}const targetPage = Number(this.jumpPage);if (isNaN(targetPage) || targetPage < 1 || targetPage > this.maxPage) {this.jumpPage = 1;} else {this.jumpPage = targetPage;}
},onJumpConfirm() {this.jumpToPage();
},jumpToPage() {// 如果输入框为空,不执行跳转if (this.jumpPage === '') {return;}// 确保jumpPage是数字类型const targetPage = Number(this.jumpPage);if (isNaN(targetPage) || targetPage < 1 || targetPage > this.maxPage) {return;}this.currentIndex = targetPage;this.change("current");
}

事件触发方法

change(e) {this.$emit("input", this.currentIndex);this.$emit("update:modelValue", this.currentIndex);this.$emit("change", {type: e,current: this.currentIndex});
}

完整代码

<template><view class="uni-pagination"><!-- #ifndef MP --><pickerv-if="showPageSize === true || showPageSize === 'true'"class="select-picker"mode="selector":value="pageSizeIndex":range="pageSizeRange"@change="pickerChange"@cancel="pickerClick"@click.native="pickerClick"><button type="default" size="mini" :plain="true"><text>{{ pageSizeRange[pageSizeIndex] }} {{ piecePerPage }}</text><uni-iconsclass="select-picker-icon"type="arrowdown"size="12"color="#999"></uni-icons></button></picker><!-- #endif --><!-- #ifndef APP-NVUE --><view class="uni-pagination__total is-phone-hide">{{ total }}</view><!-- #endif --><viewclass="uni-pagination__btn":class="currentIndex === 1? 'uni-pagination--disabled': 'uni-pagination--enabled'":hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'":hover-start-time="20":hover-stay-time="70"@click="clickLeft"><template v-if="showIcon === true || showIcon === 'true'"><uni-icons color="#666" size="16" type="left" /></template><template v-else><text class="uni-pagination__child-btn">{{ prevPageText }}</text></template></view><view class="uni-pagination__num uni-pagination__num-flex-none"><view class="uni-pagination__num-current"><textclass="uni-pagination__num-current-text is-pc-hide current-index-text">{{ currentIndex }}</text><text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text><!-- #ifndef APP-NVUE --><viewv-for="(item, index) in paper":key="index":class="{ 'page--active': item === currentIndex }"class="uni-pagination__num-tag tag--active is-phone-hide"@click.top="selectPage(item, index)"><text>{{ item }}</text></view><!-- #endif --></view></view><view class="uni-pagination__jump"><text class="uni-pagination__jump-text">前往</text><inputclass="uni-pagination__jump-input"type="number":value="jumpPage"@input="onJumpInput"@blur="onJumpBlur"@confirm="onJumpConfirm":placeholder="'1-' + maxPage":maxlength="String(maxPage).length"/><text class="uni-pagination__jump-text"></text><!-- <button class="uni-pagination__jump-btn" size="mini" type="primary" @click="jumpToPage">确定</button> --></view><viewclass="uni-pagination__btn":class="currentIndex >= maxPage? 'uni-pagination--disabled': 'uni-pagination--enabled'":hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'":hover-start-time="20":hover-stay-time="70"@click="clickRight"><template v-if="showIcon === true || showIcon === 'true'"><uni-icons color="#666" size="16" type="right" /></template><template v-else><text class="uni-pagination__child-btn">{{ nextPageText }}</text></template></view></view>
</template><script>
/*** Pagination 分页器* @description 分页器组件,用于展示页码、请求数据等* @tutorial https://ext.dcloud.net.cn/plugin?id=32* @property {String} prevText 左侧按钮文字* @property {String} nextText 右侧按钮文字* @property {String} piecePerPageText 条/页文字* @property {Number} current 当前页* @property {Number} total 数据总量* @property {Number} pageSize 每页数据量* @property {Boolean} showIcon = [true|false] 是否以 icon 形式展示按钮* @property {Boolean} showPageSize = [true|false] 是否展示每页条数* @property {Array} pageSizeRange = [20, 50, 100, 500] 每页条数选框* @event {Function} change 点击页码按钮时触发 ,e={type,current} current为当前页,type值为:next/prev,表示点击的是上一页还是下一个* * @event {Function} pageSizeChange 当前每页条数改变时触发 ,e={pageSize} pageSize 为当前所选的每页条数*/import { initVueI18n } from "@dcloudio/uni-i18n";
import messages from "./i18n/index.js";
const { t } = initVueI18n(messages);
export default {name: "UniPagination",emits: ["update:modelValue", "input", "change", "pageSizeChange"],props: {value: {type: [Number, String],default: 1,},modelValue: {type: [Number, String],default: 1,},prevText: {type: String,},nextText: {type: String,},piecePerPageText: {type: String,},current: {type: [Number, String],default: 1,},total: {// 数据总量type: [Number, String],default: 0,},pageSize: {// 每页数据量type: [Number, String],default: 10,},showIcon: {// 是否以 icon 形式展示按钮type: [Boolean, String],default: false,},showPageSize: {// 是否以 icon 形式展示按钮type: [Boolean, String],default: false,},pagerCount: {type: Number,default: 7,},pageSizeRange: {type: Array,default: () => [20, 50, 100, 500],},},data() {return {pageSizeIndex: 0,currentIndex: 1,paperData: [],pickerShow: false,jumpPage: 1,};},computed: {piecePerPage() {return this.piecePerPageText || t("uni-pagination.piecePerPage");},prevPageText() {return this.prevText || t("uni-pagination.prevText");},nextPageText() {return this.nextText || t("uni-pagination.nextText");},maxPage() {let maxPage = 1;let total = Number(this.total);let pageSize = Number(this.pageSize);if (total && pageSize) {maxPage = Math.ceil(total / pageSize);}return maxPage;},paper() {const num = this.currentIndex;// TODO 最大页数const pagerCount = this.pagerCount;// const total = 181const total = this.total;const pageSize = this.pageSize;let totalArr = [];let showPagerArr = [];let pagerNum = Math.ceil(total / pageSize);for (let i = 0; i < pagerNum; i++) {totalArr.push(i + 1);}showPagerArr.push(1);const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2];totalArr.forEach((item, index) => {if ((pagerCount + 1) / 2 >= num) {if (item < pagerCount + 1 && item > 1) {showPagerArr.push(item);}} else if (num + 2 <= totalNum) {if (item > num - (pagerCount + 1) / 2 &&item < num + (pagerCount + 1) / 2) {showPagerArr.push(item);}} else {if ((item > num - (pagerCount + 1) / 2 ||pagerNum - pagerCount < item) &&item < totalArr[totalArr.length - 1]) {showPagerArr.push(item);}}});if (pagerNum > pagerCount) {if ((pagerCount + 1) / 2 >= num) {showPagerArr[showPagerArr.length - 1] = "...";} else if (num + 2 <= totalNum) {showPagerArr[1] = "...";showPagerArr[showPagerArr.length - 1] = "...";} else {showPagerArr[1] = "...";}showPagerArr.push(totalArr[totalArr.length - 1]);} else {if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else {showPagerArr.shift();showPagerArr.push(totalArr[totalArr.length - 1]);}}return showPagerArr;},},watch: {current: {immediate: true,handler(val, old) {if (val < 1) {this.currentIndex = 1;} else {this.currentIndex = val;}},},value: {immediate: true,handler(val) {if (Number(this.current) !== 1) return;if (val < 1) {this.currentIndex = 1;} else {this.currentIndex = val;}},},pageSizeIndex(val) {this.$emit("pageSizeChange", this.pageSizeRange[val]);},currentIndex: {handler(val) {// 当当前页码变化时,同步更新输入框的值// 只有当jumpPage与currentIndex不同且jumpPage不为空时才更新,避免循环更新if (this.jumpPage !== val && this.jumpPage !== '') {this.jumpPage = val;}},immediate: true,},},methods: {pickerChange(e) {this.pageSizeIndex = e.detail.value;this.pickerClick();},pickerClick() {// #ifdef H5const body = document.querySelector("body");if (!body) return;const className = "uni-pagination-picker-show";this.pickerShow = !this.pickerShow;if (this.pickerShow) {body.classList.add(className);} else {setTimeout(() => body.classList.remove(className), 300);}// #endif},// 选择标签selectPage(e, index) {if (parseInt(e)) {this.currentIndex = e;this.change("current");} else {let pagerNum = Math.ceil(this.total / this.pageSize);// let pagerNum = Math.ceil(181 / this.pageSize)// 上一页if (index <= 1) {if (this.currentIndex - 5 > 1) {this.currentIndex -= 5;} else {this.currentIndex = 1;}return;}// 下一页if (index >= 6) {if (this.currentIndex + 5 > pagerNum) {this.currentIndex = pagerNum;} else {this.currentIndex += 5;}return;}}},clickLeft() {if (Number(this.currentIndex) === 1) {return;}this.currentIndex -= 1;this.change("prev");},clickRight() {if (Number(this.currentIndex) >= this.maxPage) {return;}this.currentIndex += 1;this.change("next");},change(e) {this.$emit("input", this.currentIndex);this.$emit("update:modelValue", this.currentIndex);this.$emit("change", {type: e,current: this.currentIndex,});},onJumpInput(e) {const value = e.detail.value;// 允许输入框为空,如果为空则设置为空字符串,否则转换为数字this.jumpPage = value === '' ? '' : Number(value) || 1;},onJumpBlur() {// 如果输入框为空,不进行验证,保持为空if (this.jumpPage === '') {return;}const targetPage = Number(this.jumpPage);if (isNaN(targetPage) || targetPage < 1 || targetPage > this.maxPage) {this.jumpPage = 1;} else {this.jumpPage = targetPage;}},onJumpConfirm() {this.jumpToPage();},jumpToPage() {// 如果输入框为空,不执行跳转if (this.jumpPage === '') {return;}// 确保jumpPage是数字类型const targetPage = Number(this.jumpPage);if (isNaN(targetPage) || targetPage < 1 || targetPage > this.maxPage) {return;}this.currentIndex = targetPage;this.change("current");},},
};
</script><style lang="scss" scoped>
$uni-primary: #2979ff !default;
.uni-pagination {margin: 40rpx 0;/* #ifndef APP-NVUE */display: flex;/* #endif */position: relative;overflow: hidden;flex-direction: row;justify-content: center;align-items: center;
}.uni-pagination__total {font-size: 14px;color: #999;margin-right: 15px;
}.uni-pagination__btn {/* #ifndef APP-NVUE */display: flex;cursor: pointer;/* #endif */padding: 0 8px;line-height: 30px;font-size: 12px;position: relative;background-color: #f0f0f0;flex-direction: row;justify-content: center;align-items: center;text-align: center;border-radius: 5px;// border-width: 1px;// border-style: solid;// border-color: $uni-border-color;
}.uni-pagination__child-btn {/* #ifndef APP-NVUE */display: flex;/* #endif */font-size: 12px;position: relative;flex-direction: row;justify-content: center;align-items: center;text-align: center;color: #666;font-size: 12px;
}.uni-pagination__num {/* #ifndef APP-NVUE */display: flex;/* #endif */flex: 1;flex-direction: row;justify-content: center;align-items: center;height: 30px;line-height: 30px;font-size: 12px;color: #666;margin: 0 5px;
}.uni-pagination__num-tag {/* #ifdef H5 */cursor: pointer;min-width: 30px;/* #endif */margin: 0 5px;height: 30px;text-align: center;line-height: 30px;// border: 1px red solid;color: #999;border-radius: 4px;// border-width: 1px;// border-style: solid;// border-color: $uni-border-color;
}.uni-pagination__num-current {/* #ifndef APP-NVUE */display: flex;/* #endif */flex-direction: row;
}.uni-pagination__num-current-text {font-size: 15px;
}.current-index-text {color: $uni-primary;
}.uni-pagination--enabled {color: #333333;opacity: 1;
}.uni-pagination--disabled {opacity: 0.5;/* #ifdef H5 */cursor: default;/* #endif */
}.uni-pagination--hover {color: rgba(0, 0, 0, 0.6);background-color: #eee;
}.tag--active:hover {color: $uni-primary;
}.page--active {color: #fff;background-color: $uni-primary;
}.page--active:hover {color: #fff;
}/* 输入框跳转样式 */
.uni-pagination__jump {/* #ifndef APP-NVUE */display: flex;/* #endif */flex-direction: row;justify-content: center;align-items: center;margin: 0 10px;
}.uni-pagination__jump-text {font-size: 12px;color: #666;margin: 0 5px;
}.uni-pagination__jump-input {width: 50px;height: 30px;min-height: fit-content;text-align: center;border: 1px solid #ddd;border-radius: 4px;font-size: 12px;color: #333;background-color: #fff;margin: 0 5px;
}.uni-pagination__jump-btn {margin-left: 5px;height: 30px;line-height: 30px;font-size: 12px;padding: 0 8px;
}/* #ifndef APP-NVUE */
.is-pc-hide {display: block;
}.is-phone-hide {display: none;
}@media screen and (min-width: 450px) {.is-pc-hide {display: none;}.is-phone-hide {display: block;}.uni-pagination__num-flex-none {flex: none;}
}/* #endif */
</style>
http://www.dtcms.com/a/265986.html

相关文章:

  • uniapp加上全局水印
  • 【如何判断Linux系统是Ubuntu还是CentOS】
  • 【Laravel】 Laravel 智能验证规则生成器
  • Java操作word实战
  • LiteHub中间件之跨域访问CORS
  • P2392 kkksc03考前临时抱佛脚(动态规划)
  • 纯前端批量下载
  • Python 爬虫实战 | 国家医保
  • MySQL 8.0 OCP 1Z0-908 题目解析(16)
  • Part 0:射影几何,变换与估计-第三章:3D射影几何与变换
  • 爬虫经验分享:淘宝整店商品爬取全过程|API接口实战
  • 【数据结构】 map 和 set
  • stm32第十三天串口发送数据
  • 从0到1实战!用Docker部署Qwerty Learner输入法的完整实践过程
  • Dijkstra 算法#图论
  • MySQL JSON数据类型完全指南:从版本演进到企业实践的深度对话
  • Windows 上使用 vscode + mingw 调试 python 程序
  • 国内MCP服务平台推荐!aibase.cn上线MCP服务器集合平台
  • 二叉树的右视图C++
  • MySQL的窗口函数介绍
  • 每日算法刷题Day41 6.28:leetcode前缀和2道题,用时1h20min(要加快)
  • golang json omitempty 标签研究
  • 图论基础算法入门笔记
  • OOM电商系统订单缓存泄漏,这是泄漏还是溢出
  • 免费一键自动化申请、续期、部署、监控所有 SSL/TLS 证书,ALLinSSL开源免费的 SSL 证书自动化管理平台
  • 【进阶篇-消息队列】——RocketMQ如何实现事务的
  • HarmonyOS ArkTS卡片堆叠滑动组件实战与原理详解(含源码)
  • 如何挖掘客户的隐性需求
  • 474. 一和零
  • 【华为od刷题(C++)】HJ22 汽水瓶