当前位置: 首页 > 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.lryc.cn/news/579404.html

相关文章:

  • SpringCloud系列(49)--SpringCloud Stream消息驱动之实现生产者
  • Rubber Band Algorithm 应力及反作用力测试
  • 运维打铁: 企业运维开发痛点之解决方案
  • ModuleNotFoundError: No module named ‘onnxruntime‘
  • 【免费.NET方案】CSV到PDF与DataTable的快速转换
  • 图论基础算法入门笔记
  • MySQL 8.0 OCP 1Z0-908 题目解析(18)
  • 深度学习2(逻辑回归+损失函数+梯度下降)
  • 在 VSCode 中高效配置自定义注释模板 (无需插件)
  • Python 中如何使用 Conda 管理版本和创建 Django 项目
  • Flowable多引擎架构搭建方案
  • 车载以太网-IP 掩码 vlan 端口
  • 前端的一些报错
  • Odoo 中国特色高级工作流审批模块研发
  • 编程基础:成员函数
  • 【LUT技术专题】3DLUT压缩-CLUT
  • 朝鲜APT组织使用Nim语言恶意软件对macOS发起隐秘Web3与加密货币攻击
  • .net wpf混淆
  • uniapp 使用ffmpeg播放rtsp
  • QT常用类和模块
  • Qt宝藏库:20+实用开源项目合集
  • Java——初始guava(1)
  • 【python】OOP:Object-Oriented Programming
  • Linux基本命令篇 —— tar命令
  • Redis缓存架构实战
  • 微算法科技(NASDAQ MLGO)基于量子图像处理的边缘检测算法:开拓图像分析新视野
  • 中国户外品牌全球竞争力榜单发布:科技突围与文化赋能重塑行业格局
  • 扫地机产品--电池是否存在类似充电宝自燃问题?
  • 【JS笔记】JS 和 noodjs 的常见操作(十)
  • 依赖属性附加属性