web技术分享| 基于vue3解决问题自己的组件库第二章:Pagination组件
时间:2025-01-11 12:20:34
lick', index); setJumpValue(); }; const handleNextClick = (index) => { ctx.emit('next-click', index); setJumpValue(); }; const handleInput = (value) => { if (!reg.test(value) SimonSimon value !== '') { jumpValue.value = oldJumpValue.value; } else { oldJumpValue.value = value; } }; const handleChange = (value) => { const max = Math.ceil(props.total / props.pageSize); if (value < 1) { jumpValue.value = 1; oldJumpValue.value = 1; } else if (value> max) { jumpValue.value = max; oldJumpValue.value = max; } cCurrentPage.value = +jumpValue.value; }; const setJumpValue = () => { jumpValue.value = cCurrentPage.value; oldJumpValue.value = cCurrentPage.value; }; watchEffect(() => { activePageSize.value = pageSizes.value[0].label; }); watchEffect(() => { if (!reg.test(props.pagerCount) || props.pagerCount 21) { throw new TypeError(MLT-pager-count value of can only be an integer greater than or equal to 7 and less than or equal to 21, but received a ${props.pagerCount}MLT-); } }); watchEffect(() => { if (!reg.test(props.pageSize)) { throw new Error('pager-size It has to be an integer greater than or equal to 1'); } }); watch(() => props.pageSize, () => { setJumpValue(); }); watchEffect(() => { if (!reg.test(props.currentPage)) { throw new Error('current-page It has to be an integer greater than or equal to 1'); } else { cCurrentPage.value = props.currentPage; } }); watchEffect(() => { if (typeof props.total !== 'number' || props.total < 0) { throw new Error('total must be a number greater than or equal to 0'); } }); watchEffect(() => { ctx.emit('current-change', cCurrentPage.value); setJumpValue(); }); return { handleSizeChange, handlePrevClick, handleNextClick, handleInput, handleChange, pageSizes, activePageSize, jumpValue, cCurrentPage, cpages } } } Pagination.vue Props const VairPagination = { background: { // 前提开启背景色 type: Boolean, default: () => { return false; } }, pageSize: { // 开本推断几条资料 type: Number, default: () => { return 10; } }, total: { // 资料总数量 type: Number, default: () => { return 0; } }, pagerCount: { // 当总页数超过该值上但会开启拉链 最少为 7 type: Number, default: () => { return 7; } }, pageSizes: { // 开本推断个数选择器的选项 type: Array, default: () => { return [10, 20, 30, 40, 50, 100]; } }, prependText: { // 后退按钮文本 type: String, default: () => { return ''; } }, suffixText: { // 前进按钮文本 type: String, default: () => { return ''; } }, disabled: { // 前提替换成 type: Boolean, default: () => { return false; } }, hideOnSinglePage: { // 只有一页时前提隐藏 type: Boolean, default: () => { return false; } }, currentPage: { // 当前页数 type: Number, default: () => { return 1; } }, layout: { // 部件样式推断顺序 type: Array, default: () => { return ['switch', 'pages', 'jump']; } }, }; // Event // size-change (number) // current-change (index) // prev-click (index) // next-click (index) export default VairPagination; Pagination.vue Style .v-pagination { display: flex; align-items: center; .v-pagination-select-box, .v-pagination-input-box { width: 120px; /deep/.v-select, /deep/.v-input { min-width: 0; } /deep/.v-input { height: 30px; .v-input-box, .input { height: 30px; .suffix { height: 25px; } } } } .v-pagination-input-box { display: flex; align-items: center; width: 120px; /deep/.v-input { width: 50px; margin: 0 6px; .input { text-indent: 0px; text-align: center; } } span { font-size: 14px; } } .disabled { cursor: not-allowed; span { color: #c0cc; } } } Pages.vue Template
{{ prependText }} {{ item }}
{{ suffixText }} Pages.vue Script import { ref, computed, watchEffect, onMounted } from 'vue'; export default { name: 'pages', props: { total: Number, pagerCount: Number, pageSize: Number, prependText: String, suffixText: String, disabled: Boolean, hideOnSinglePage: Boolean, background: Boolean || String, modelValue: Number }, setup (props, ctx) { const medianButtonList = ref([]); const prependDisabled = ref(true); const suffixDisabled = ref(true); const doubleLeft = ref(false); const doubleRight = ref(false); const liList = ref([]); const prepend = ref(null); const suffix = ref(null); const cPages = ref(null); onMounted(() => { watchEffect(() => { liList.value.forEach(item => { !props.background SimonSimon (item.style.backgroundColor = 'transparent'); }); !props.background SimonSimon (prepend.value.style.backgroundColor = 'transparent'); !props.background SimonSimon (suffix.value.style.backgroundColor = 'transparent'); }); watchEffect(() => { if (calculatePagesButtonList.value.length <= 1 SimonSimon props.hideOnSinglePage) { cPages.value.style.display = 'none'; } else { cPages.value.style.display = 'flex'; } }); }); const handlePagesLiClick = (index) => { if (props.disabled) return if (typeof index === 'number' SimonSimon props.modelValue !== index) { ctx.emit('update:modelValue', index); ctx.emit('current-change', index); } }; const handleMouseEnter = (item) => { if (props.disabled) return if (item === 'prepend') { doubleLeft.value = true; } else if (item === 'suffix') { doubleRight.value = true; } }; const handleMouseLee = (item) => { if (props.disabled) return if (item === 'prepend') { doubleLeft.value = false; } else if (item === 'suffix') { doubleRight.value = false; } }; const handleIClick = (item) => { if (props.disabled) return if (item === 'prepend') { const num = props.modelValue - 3; ctx.emit('update:modelValue', num < 1? 1 : num); } else if (item === 'suffix') { const maxPages = Math.ceil(props.total / props.pageSize); const num = props.modelValue + 3; ctx.emit('update:modelValue', num> maxPages? maxPages : num); } ctx.emit('current-change', props.modelValue); }; const handlePrependClick = () => { if (props.disabled) return if (props.modelValue <= 1) return; ctx.emit('update:modelValue', props.modelValue - 1); ctx.emit('prev-click', props.modelValue); }; const handleSuffixClick = () => { if (props.disabled) return const value = calculatePagesButtonList.value; const item = value[value.length - 1]; if (props.modelValue>= item) return; ctx.emit('update:modelValue', props.modelValue + 1); ctx.emit('next-click', props.modelValue); }; const calculatePagesButtonList = computed(() => { const value = props.modelValue; const maxPages = Math.ceil(props.total / props.pageSize); const bool = (maxPages - props.pagerCount)> 0; const maxCurrentPage = (value - maxPages)> 0? maxPages : value; const pagerCountHalf = Math.ceil((props.pagerCount - 2) / 2); const a = (maxCurrentPage + pagerCountHalf) < maxPages; const b = (maxCurrentPage - pagerCountHalf) <= 2; let pagesButtonList = []; if (bool) { if (b) { for(let i = 1; i < props.pagerCount; i++) { pagesButtonList.push(i); } pagesButtonList.push('suffix'); pagesButtonList.push(maxPages); } else if (a) { pagesButtonList.push(1); pagesButtonList.push('prepend'); for(let i = (maxCurrentPage - pagerCountHalf + 1); i < (maxCurrentPage + pagerCountHalf); i++) { pagesButtonList.push(i); } pagesButtonList.push('suffix'); pagesButtonList.push(maxPages); } else if (!a) { pagesButtonList.push(1); pagesButtonList.push('prepend'); for(let i = (maxPages - props.pagerCount + 2); i <= maxPages; i++) { pagesButtonList.push(i); } } } else { for (let i = 1; i <= maxPages; i++) { pagesButtonList.push(i); } } return pagesButtonList; }); const calculateCurrentPage = () => { const value = calculatePagesButtonList.value; const item = value[value.length - 1]; ctx.emit('update:modelValue', props.modelValue> item? item : props.modelValue); }; watchEffect(() => { calculateCurrentPage(); }); watchEffect(() => { const value = calculatePagesButtonList.value; const item = value[value.length - 1]; prependDisabled.value = props.modelValue === 1; suffixDisabled.value = props.modelValue>= item; }); return { calculatePagesButtonList, medianButtonList, prependDisabled, suffixDisabled, handlePagesLiClick, handlePrependClick, handleSuffixClick, handleMouseEnter, handleMouseLee, handleIClick, doubleRight, doubleLeft, liList, prepend, cPages, suffix } } } Pages.vue Style .v-pages { display: flex; align-items: center; margin: 0 14px; .prepend, .suffix { display: flex; align-items: center; justify-content: center; min-width: 30px; min-height: 28px; box-sizing: border-box; padding: 0 6px; margin: 0 5px; background-color:#F4F4F5; cursor: pointer; p, i { font-size: 12px; color: #333; font-weight: 600; } Simon:hover { p, i { color: #409EFF; } } } .prependDisabled, .suffixDisabled { p, i { color: #CDC9CC !important; } cursor: not-allowed; } .v-pages-ul { display: flex; align-items: center; .v-pages-li { margin: 0 5px; background-color:#F4F4F5; cursor: pointer; span, i { display: block; min-width: 30px; box-sizing: border-box; padding: 0 6px; line-height: 28px; text-align: center; font-size: 12px; color: #333; font-weight: 600; } Simon:hover { span, i { color: #409EFF; } } } .activeLi { background-color:#409EFF; span { color: #fff; } .color { color: #409EFF !important; } Simon:hover { span { color: #fff; } } } } .disabled { p, i, span { color: #c0cc !important; } cursor: not-allowed !important; } } index.js 出口文件中替换成部件 // Pagination 分页 import Pagination from './components/Pagination/Pagination.vue'; import Pages from './components/Pagination/components/Pages.vue'; const Vair = function(Vue) { Vue.component(MLT-v-${Pagination.name}MLT-, Pagination); Vue.component(MLT-v-${Pages.name}MLT-, Pages); } export default Vair; 用作部件 在main.js中替换成 import { createApp } from 'vue'; import App from './App.vue'; import Vair from './libs/vair/index.js'; const app = createApp(App); app.use(Vair).mount('#app'); App.vue中调用 import { ref } from 'vue'; export default { setup () { const pageSizes = ref([10, 20, 30, 40, 50, 100]); const pageSize = ref(10); const total = ref(50500); const currentPage = ref(10); const pagerCount = ref(7); const background = ref(true); const prependText = ref('prepre'); const suffixText = ref('nextnext'); const disabled = ref(false); const handleCurrentChange = (index) => { console.log(index) }; const handlePrevClick = (index) => { console.log('handlePrevClick 触发了', index); }; const handleNextClick = (index) => { console.log('handleNextClick 触发了', index); }; const handleSizeChange = (number) => { pageSize.value = number; }; return { pageSizes, pageSize, total, disabled, currentPage, pagerCount, handleCurrentChange, handlePrevClick, handleNextClick, handleSizeChange, background, prependText, suffixText } } } div { margin-top: 20px; } 敏感度展示 。深圳哪家医院专业做人流
北京看白癜风哪家医院好
江苏男科医院哪家比较专业
杭州妇科专科医院哪家好
眼睛充血是什么原因引起的
新冠阳性吃什么药
艾德莫拉片治疗类风湿效果好吗
先诺欣多少钱一盒
脸色黄怎么调理
艾得辛对类风湿管用吗
北京看白癜风哪家医院好
江苏男科医院哪家比较专业
杭州妇科专科医院哪家好
眼睛充血是什么原因引起的
新冠阳性吃什么药
艾德莫拉片治疗类风湿效果好吗
先诺欣多少钱一盒
脸色黄怎么调理
艾得辛对类风湿管用吗
上一篇: 为什么你的利息只有三四千?
相关阅读
- .“高温下石墩能治月经”消息传出后,出现人传人现象,医生提议
- .通知!7月8日-10日开展部分区域组员核酸筛查
- .每天多睡一不间断,2周就能瘦一斤?科学家真的没骗人
- .训导主任提醒:暑假千万别让孩子染上这九个坏习惯!(内附走心建议)
- .耳聋耳背知识分享;还有夏天助听器保养小技巧
- .世界过敏疾病日:孩子过敏怎么办 专家为您支招
- .超300亿血管介入AI市场第一股IPO,推高市场天花板
- .即日施行!东山六院最新就诊须知
- .相当于“喝油”的4种零食,有人还天天喝,瘦不下来也是活该!
- .世界过敏反应疾病日丨别把鼻炎当感冒!我国过敏反应鼻炎患者高达2.4亿
- .六种怪异步态 暗藏健康困局
- .夏末喝什么水最解暑
- .啤酒肚不是“幸福凉”!科动来消除
- .哪种运动适合自己?三句话有趣看懂
- .咖啡不仅能“续命” 还能降低痛风风险
- .增寿和折寿的食物表单 是时候更换你的食谱了
- .老年人为啥要打新冠抗生素?
- .BA.5奥密克戎变异株不同以往,不但传染性高, 心绞痛率也有所提升
- .当小山村接入5G互联
- .减肥门诊开出多样化药品
友情链接: