2026/1/13 13:14:36
网站建设
项目流程
discuz做淘客网站,免费源码资源源码站入口,梅州网站建设求职简历,海口省建设厅网站Vue 与 ElementUI 实现分页、HTTP 封装及农历转换的工程实践
在构建现代前端应用时#xff0c;我们常常需要处理大量数据展示、统一管理接口请求#xff0c;并增强用户对时间信息的理解。尤其是在政务系统、日程提醒、文化类平台等场景中#xff0c;不仅要呈现公历日期我们常常需要处理大量数据展示、统一管理接口请求并增强用户对时间信息的理解。尤其是在政务系统、日程提醒、文化类平台等场景中不仅要呈现公历日期还需标注农历节日和节气以提升本土化体验。本文将围绕一个真实可用的技术栈组合——Vue 2 ElementUI深入探讨如何在一个项目中高效整合三大核心功能- 基于el-pagination的智能分页展示- 使用 Axios 封装的可复用 HTTP 请求模块- 支持节日识别的公历转农历工具整个实现过程注重代码结构清晰、逻辑解耦与工程可维护性适合用于中后台管理系统或内容型 Web 应用的快速开发。当我们面对一个包含数百条文章的数据列表时直接渲染显然不现实。更合理的做法是通过分页控制每页显示数量既减轻浏览器负担也提升用户体验。ElementUI 提供了开箱即用的el-pagination组件配合 Vue 的计算属性computed我们可以轻松实现本地分页template div classarticle-page h2技术博客列表/h2 ul classarticle-list li v-for(item, index) in paginatedList :keyindex classarticle-item h3{{ item.title }}/h3 p{{ item.summary }}/p small发布于{{ item.date }}/small /li /ul div classpagination-container el-pagination current-changehandlePageChange :current-pagecurrentPage :page-sizepageSize :totalarticleList.length layoutprev, pager, next, total background / /div /div /template script export default { name: ArticleList, data() { return { currentPage: 1, pageSize: 8, articleList: [] } }, computed: { paginatedList() { const start (this.currentPage - 1) * this.pageSize; const end start this.pageSize; return this.articleList.slice(start, end); } }, methods: { handlePageChange(page) { this.currentPage page; } }, mounted() { this.fetchArticles(); } } /script这里的paginatedList是典型的计算属性用法它依赖currentPage和pageSize自动响应式更新无需手动触发重计算。当用户点击页码时current-change回调更新当前页视图随之刷新。值得注意的是这种模式适用于前端已有完整数据的情况。若后端支持分页查询建议改为传递page参数到 API减少网络传输量。为了统一管理所有 API 调用避免重复编写请求头、错误处理逻辑封装一个全局 HTTP 工具是必要的工程实践。我们基于 Axios 创建src/utils/request.js并加入拦截器机制实现权限认证与异常统一处理import axios from axios const service axios.create({ baseURL: process.env.NODE_ENV production ? https://api.example.com : /api, timeout: 10000, headers: { Content-Type: application/json } }) // 请求拦截添加 token service.interceptors.request.use( config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer ${token} } return config }, error { console.error(Request Error:, error) return Promise.reject(error) } ) // 响应拦截统一错误提示 service.interceptors.response.use( response { const res response.data if (res.code ! 200 res.code ! undefined) { alert(Error: ${res.message || 未知错误}) return Promise.reject(new Error(res.message || Error)) } return res }, error { if (error.response) { switch (error.response.status) { case 401: alert(未授权请登录) break case 404: alert(请求资源不存在) break default: alert(网络异常) } } return Promise.reject(error) } ) export default service这个封装带来的好处非常明显环境适配根据NODE_ENV切换基础 URL开发调试更方便安全加固自动携带 Token防止未授权访问错误集中处理无论是业务码非 200 还是 HTTP 状态码异常都能及时反馈给用户易于扩展后续可加入 loading 拦截、缓存策略、重试机制等。在组件中使用也非常简洁import request from /utils/request export default { methods: { async fetchArticles() { try { const res await request({ url: /articles, method: get }) this.articleList res.data || [] } catch (err) { this.articleList [] } } } }一行调用即可完成带拦截、鉴权、错误处理的请求极大提升了开发效率。传统节日和二十四节气在中国文化中具有重要意义。在日历类应用中仅显示公历显然不够友好。为此我们需要将公历日期转换为农历并标注节日与节气。我们创建src/utils/calendar.js引入轻量级农历算法库适用于 1900–2100 年const calendar { lunarInfo: [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // ... 中间省略实际项目请补全全部数据 ], solarTerm: [ 小寒,大寒,立春,雨水,惊蛰,春分,清明,谷雨, 立夏,小满,芒种,夏至,小暑,大暑,立秋,处暑, 白露,秋分,寒露,霜降,立冬,小雪,大雪,冬至 ], festival: { 1-1: { title: 元旦 }, 5-1: { title: 劳动节 }, 10-1: { title: 国庆节 }, 12-25: { title: 圣诞节 } }, lFestival: { 1-1: { title: 春节 }, 1-15: { title: 元宵节 }, 5-5: { title: 端午节 }, 8-15: { title: 中秋节 }, 12-8: { title: 腊八节 } }, solar2lunar(solarYear, solarMonth, solarDay) { // 此处为简化示意实际需完整实现 offset 计算、闰月判断等 const festivals this.festival[${solarMonth}-${solarDay}] return { IDayCn: ${solarDay}, IMonthCn: ${solarMonth}月, festival: festivals ? festivals.title : null, Term: null, isLeap: false, Animal: [鼠,牛,虎,兔,龙,蛇,马,羊,猴,鸡,狗,猪][(solarYear - 4) % 12] } } } export default calendar⚠️ 注意完整版lunarInfo数组包含约 250 项用于精确计算每年的农历月份天数与闰月位置。建议从开源项目如 jjonline/calendar 获取完整算法。在 Vue 组件中集成该工具结合el-calendar自定义单元格内容template el-calendar v-modelcurrentDate template #date-cell{data} div clickonDateClick(data) span classday{{ data.day.split(-)[2] }}/span div classlunar-info :class{ holiday: isHoliday(data) } {{ getLunarText(data) }} /div /div /template /el-calendar /template script import calendar from /utils/calendar export default { data() { return { currentDate: new Date() } }, methods: { onDateClick(data) { console.log(Clicked date:, data.day) }, getLunarText(data) { const [y, m, d] data.day.split(-).map(Number) const lunar calendar.solar2lunar(y, m, d) if (lunar.festival) return lunar.festival if (lunar.Term) return lunar.Term return lunar.IMonthCn lunar.IDayCn }, isHoliday(data) { const [y, m, d] data.day.split(-).map(Number) const lunar calendar.solar2lunar(y, m, d) return !!(lunar.festival || lunar.Term) } } } /script style scoped .el-calendar ::v-deep .el-calendar-day { height: 100px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .day { font-size: 14px; font-weight: bold; } .lunar-info { font-size: 11px; color: #999; margin-top: 4px; } .holiday { color: #f56c6c !important; font-weight: bold; } /style效果上每一天都会显示对应的农历信息节日或节气则以红色高亮视觉区分明显用户一眼即可识别重要日子。最终我们将三个模块融合成一个完整的仪表盘页面左侧展示分页文章列表右侧嵌入农历日历!-- ArticleWithCalendar.vue -- template div classdashboard h1技术文章与日历系统/h1 div classcontent-area !-- 左侧文章列表 -- section classarticles h2最新文章/h2 ul classarticle-list li v-for(art, idx) in paginatedList :keyidx router-link :to/article/ art.id {{ art.title }} em{{ art.date }}/em /router-link /li /ul el-pagination current-changehandlePageChange :current-pagecurrentPage :page-size8 :totalarticleList.length layoutprev, pager, next, total / /section !-- 右侧日历 -- section classcalendar-section el-calendar v-modeltoday template #date-cell{data} div span{{ data.day.split(-)[2] }}/span div classlunar-tip :class{fest: isFestival(data)} {{ lunarLabel(data) }} /div /div /template /el-calendar /section /div /div /template script import request from /utils/request import calendar from /utils/calendar export default { data() { return { currentPage: 1, articleList: [], today: new Date() } }, computed: { paginatedList() { const start (this.currentPage - 1) * 8 return this.articleList.slice(start, start 8) } }, methods: { handlePageChange(page) { this.currentPage page }, async fetchArticles() { try { const res await request.get(/articles) this.articleList res.data.map(d ({ id: d.id, title: d.title, date: d.pub_date })) } catch (e) { this.articleList [] } }, lunarLabel(data) { const [y, m, d] data.day.split(-).map(Number) const lunar calendar.solar2lunar(y, m, d) if (lunar.festival) return lunar.festival if (lunar.Term) return lunar.Term return lunar.IMonthCn lunar.IDayCn }, isFestival(data) { const [y, m, d] data.day.split(-).map(Number) const lunar calendar.solar2lunar(y, m, d) return !!lunar.festival || !!lunar.Term } }, mounted() { this.fetchArticles() } } /script style scoped .dashboard { max-width: 1200px; margin: 0 auto; padding: 20px; } .content-area { display: flex; gap: 30px; } .articles { flex: 1; } .calendar-section { width: 300px; } .article-list { list-style: none; padding: 0; } .article-list li { padding: 8px 0; border-bottom: 1px solid #eee; } .lunar-tip { font-size: 12px; color: #aaa; } .fest { color: #e60000; font-weight: bold; } /style这样的布局兼顾功能性与美观性特别适合资讯门户、企业内网、个人博客后台等场景。这套方案的价值不仅在于实现了具体功能更在于其体现的工程化思维分页设计避免一次性加载过多数据保障性能HTTP 封装实现请求标准化降低维护成本农历工具提升产品文化感知力增强用户体验。这些模式均可独立抽离为公共模块在多个项目中复用。例如可将calendar打包为 NPM 包或将请求拦截器抽象为插件形式。未来还可进一步优化- 引入 Vuex 或 Pinia 管理全局状态如当前页、用户信息- 使用 TypeScript 增强类型安全- 接入真实农历 API 提供更高精度服务- 支持主题切换与国际化。前端开发不仅是“写页面”更是构建可持续演进的系统。从一个小功能出发思考其背后的架构意义才能真正写出高质量、易维护的代码。