ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

中国海洋大学2026年夏季《移动软件开发》实验3:高校新闻网

2026/9/2 21:12:07 拓冰建站 浏览量
中国海洋大学2026年夏季《移动软件开发》实验3:高校新闻网 项目内容姓名和学号王晨旭24020007119本实验属于哪门课程中国海洋大学26夏《移动软件开发》实验名称实验3高校新闻网博客地址上传后填Github仓库地址GitHub/Gitee仓库地址上传后填一、实验概述本次实验的目标是制作一个以海大为主题的高校新闻小程序lab03。小程序包含三大核心页面首页展示轮播图与热点新闻列表新闻详情页展示文章正文并提供收藏/取消收藏功能个人中心页支持微信登录并展示我的收藏列表。在实验文档要求的基础上本次实现还做了以下扩展与优化自定义 TabBar使用custom-tab-bar组件并用纯 CSS 绘制首页/我的图标避免依赖图片素材提升可维护性。夜间模式详情页支持一键切换日间/夜间主题并同步导航栏与页面背景色。新版登录能力我的页采用微信官方推荐的chooseAvatar与typenickname头像昵称填写能力登录态持久化存储支持退出登录。统一收藏管理在utils/common.js中使用单一缓存键my_favorite_news存储收藏数组便于增删、查重与去重。二、实验步骤1. 创建小程序项目在微信开发者工具中新建项目lab3选择「小程序」→ 目录选择空白文件夹AppID 使用测试号后端服务选择「不使用云服务」模板选择「JS 基础模板」。2. 全局配置app.json在app.json中注册首页、详情页、个人中心页配置导航栏样式并开启自定义 TabBar{ pages: [ pages/index/index, pages/logs/logs, pages/detail/detail, pages/my/my ], window: { navigationBarBackgroundColor: #328EEB, navigationBarTitleText: 我的新闻网, navigationBarTextStyle: white }, tabBar: { custom: true, color: #999999, selectedColor: #328EEB, backgroundColor: #ffffff, borderStyle: white, list: [ { pagePath: pages/index/index, text: 首页 }, { pagePath: pages/my/my, text: 我的 } ] }, style: v2, sitemapLocation: sitemap.json }3. 自定义底部导航栏custom-tab-bar通过custom-tab-bar/index.js维护导航项与选中状态点击时调用wx.switchTab切换页面Component({ data: { selected: 0, list: [ { pagePath: /pages/index/index, text: 首页 }, { pagePath: /pages/my/my, text: 我的 } ] }, methods: { switchTab(e) { const idx e.currentTarget.dataset.index const path this.data.list[idx].pagePath wx.switchTab({ url: path }) } } })在custom-tab-bar/index.wxml中通过wx:if分别渲染首页图标与个人图标并配合active类实现选中高亮。4. 首页实现pages/indexindex.wxml页面结构轮播图使用swiper组件循环展示swiperImg数组中的新闻图片并开启indicator-dots、autoplay、circular。热点新闻列表使用wx:for遍历newsList每个新闻项包含海报缩略图、标题与日期点击后携带id跳转到详情页。!-- 幻灯片 -- swiper classbanner indicator-dotstrue autoplaytrue interval5000 duration500 circulartrue swiper-item wx:for{{swiperImg}} wx:keyindex image src{{item.src}} modeaspectFill/image /swiper-item /swiper !-- 新闻列表 -- view classsection-title热点新闻/view view classnews-list view classnews-card wx:for{{newsList}} wx:keyid bindtapgoToDetail>var common require(../../utils/common.js) Page({ data: { swiperImg: [ { src: /images/news1.jpg }, { src: /images/news3.jpg }, { src: /images/news4.jpg } ], newsList: [] }, onLoad: function (options) { let list common.getNewList() this.setData({ newsList: list }) }, onShow: function () { if (this.getTabBar typeof this.getTabBar function) { this.getTabBar().setData({ selected: 0 }) } }, goToDetail: function (e) { let id e.currentTarget.dataset.id wx.navigateTo({ url: ../detail/detail?id id }) } })5. 新闻详情页实现pages/detaildetail.wxml页面结构文章标题、发布日期与夜间模式切换按钮。新闻海报大图。新闻正文内容。收藏按钮根据isAdd状态显示「已收藏」或「添加收藏」。view classdetail-container {{isDark ? dark : }} view classarticle-header view classarticle-header-top text classarticle-title{{article.title}}/text view classtheme-switch bindtaptoggleDark text classtheme-switch-icon{{isDark ? ☀ : ☾}}/text text classtheme-switch-text{{isDark ? 日间 : 夜间}}/text /view /view text classarticle-date{{article.add_date}}/text /view image classarticle-poster src{{article.poster}} modeaspectFill/image view classarticle-content text{{article.content}}/text /view button classfav-btn {{isAdd ? fav-active : }} bindtap{{isAdd ? cancelFavorites : addFavorites}} {{isAdd ? ❤️ 已收藏 : ♡ 添加收藏}} /button /viewdetail.js页面逻辑var common require(../../utils/common.js) const DARK_MODE_KEY dark_mode Page({ data: { article: {}, isAdd: false, isDark: false }, onLoad: function (options) { let id options.id let result common.getNewsDetail(id) if (result.code 200) { this.setData({ article: result.news, isAdd: common.isFavorite(id) }) } let isDark !!wx.getStorageSync(DARK_MODE_KEY) this.setData({ isDark: isDark }) this.applyNavigationBarColor(isDark) }, onShow: function () { this.applyNavigationBarColor(this.data.isDark) }, onHide: function () { if (this.data.isDark) this.applyNavigationBarColor(false) }, onUnload: function () { if (this.data.isDark) this.applyNavigationBarColor(false) }, toggleDark: function () { let isDark !this.data.isDark this.setData({ isDark: isDark }) wx.setStorageSync(DARK_MODE_KEY, isDark) this.applyNavigationBarColor(isDark) wx.showToast({ title: isDark ? 已开启夜间模式 : 已关闭夜间模式, icon: none, duration: 1200 }) }, applyNavigationBarColor: function (isDark) { wx.setNavigationBarColor({ backgroundColor: isDark ? #1c1c1e : #328EEB, frontColor: #ffffff }) if (wx.setBackgroundColor) { wx.setBackgroundColor({ backgroundColor: isDark ? #1c1c1e : #f8f9fb }) } }, addFavorites: function () { common.addFavorite(this.data.article) this.setData({ isAdd: true }) }, cancelFavorites: function () { common.removeFavorite(this.data.article.id) this.setData({ isAdd: false }) } })6. 个人中心页实现pages/mymy.wxml页面结构顶部个人信息卡片已登录显示头像、昵称与退出登录未登录显示默认头像与登录按钮。我的收藏列表展示收藏数量与收藏新闻支持点击进入详情无收藏时显示空状态。授权弹窗与头像昵称填写面板点击登录后先申请授权再引导用户选择头像、填写昵称。关键结构片段!-- 个人信息 -- view classprofile-card block wx:if{{isLogin}} image classavatar src{{src || /images/my1.png}}/image text classnickname{{nickName}}/text text classsub-text欢迎回来/text text classlogout-text bindtaplogout退出登录/text /block view wx:else classlogin-wrap image classavatar default-avatar src/images/my1.png/image button classlogin-btn bindtaponLoginTap点击登录/button text classsub-text登录后可同步收藏/text /view /view !-- 收藏列表 -- view classfavorite-section view classsection-header text classsection-title我的收藏/text text classsection-count{{number}}/text /view view classfavorite-list wx:if{{number 0}} view classfavorite-card wx:for{{newsList}} wx:keyid bindtapgoToDetail>var common require(../../utils/common.js) const USER_INFO_KEY user_info Page({ data: { isLogin: false, src: , nickName: , number: 0, newsList: [], showAuth: false, showFill: false, tempAvatar: , tempNickName: }, noop: function () {}, onLoad: function () { let info wx.getStorageSync(USER_INFO_KEY) if (info info.nickName) { this.setData({ isLogin: true, src: info.avatarUrl || , nickName: info.nickName }) } }, onLoginTap: function () { this.setData({ showAuth: true, showFill: false }) }, allowAuth: function () { this.setData({ showAuth: false, showFill: true }) }, onChooseAvatar: function (e) { let url (e.detail e.detail.avatarUrl) || if (!url) return // 临时文件需转存为永久路径 let isTemp url.indexOf(wxfile://) 0 || url.indexOf(file://) 0 || url.indexOf(http://tmp/) 0 if (!isTemp) { this.setData({ tempAvatar: url }) return } let ext url.match(/\.[a-zA-Z0-9](?:\?|$)/) ext ext ? ext[0].replace(?, ) : .png let targetPath wx.env.USER_DATA_PATH /avatar_ Date.now() ext wx.getFileSystemManager().saveFile({ tempFilePath: url, filePath: targetPath, success: (res) this.setData({ tempAvatar: res.savedFilePath }) }) }, onNickNameInput: function (e) { this.setData({ tempNickName: e.detail.value }) }, confirmFill: function () { let nickName (this.data.tempNickName || ).trim() if (!this.data.tempAvatar || !nickName) { wx.showToast({ title: 请完善头像和昵称, icon: none }) return } this.loginSuccess(this.data.tempAvatar, nickName) }, loginSuccess: function (avatarUrl, nickName) { wx.setStorageSync(USER_INFO_KEY, { avatarUrl: avatarUrl, nickName: nickName, loginTime: Date.now() }) this.setData({ isLogin: true, src: avatarUrl, nickName: nickName, showFill: false }) this.getMyFavorites() }, logout: function () { wx.removeStorageSync(USER_INFO_KEY) this.setData({ isLogin: false, src: , nickName: , newsList: [], number: 0 }) }, getMyFavorites: function () { let myList common.getFavorites() this.setData({ newsList: myList, number: myList.length }) }, onShow: function () { if (this.getTabBar typeof this.getTabBar function) { this.getTabBar().setData({ selected: 1 }) } if (this.data.isLogin) { this.getMyFavorites() } }, goToDetail: function (e) { let id e.currentTarget.dataset.id wx.navigateTo({ url: ../detail/detail?id id }) } })7. 公共数据与收藏管理utils/common.jscommon.js集中管理模拟新闻数据与收藏逻辑封装了getNewList、getNewsDetail、isFavorite、addFavorite、removeFavorite、getFavorites等方法便于各页面复用// 模拟新闻数据使用近期海大新闻 var newsList [ { id: 1, title: 中国海洋大学2026级研究生开学典礼举行, poster: /images/news1.jpg, content: 本站讯 海纳新知逐梦启航。8月24日中国海洋大学2026级研究生开学典礼在崂山校区综合体育馆举行。……, add_date: 2026-08-24 } // ... 其他新闻 ] const FAVORITES_KEY my_favorite_news function getNewList() { return newsList } function getNewsDetail(id) { for (var i 0; i newsList.length; i) { if (newsList[i].id id) { return { code: 200, news: newsList[i] } } } return { code: 404, news: null } } function _readFavorites() { let list wx.getStorageSync(FAVORITES_KEY) return (!list || !Array.isArray(list)) ? [] : list } function isFavorite(id) { let list _readFavorites() return list.some(item item item.id id) } function addFavorite(news) { if (!news || !news.id) return let list _readFavorites().filter(item !(item item.id news.id)) list.unshift(news) wx.setStorageSync(FAVORITES_KEY, list) } function removeFavorite(id) { let list _readFavorites().filter(item !(item item.id id)) wx.setStorageSync(FAVORITES_KEY, list) } function getFavorites() { return _readFavorites().filter(item item typeof item object item.id item.title) } module.exports { getNewList, getNewsDetail, isFavorite, addFavorite, removeFavorite, getFavorites }三、实验结果小程序运行正常主要功能如下首页顶部自动轮播展示海大新闻图片并带有指示点。首页新闻列表以卡片形式展示新闻缩略图、标题与发布日期。点击新闻卡片可跳转至详情页查看完整新闻内容与海报。详情页支持收藏/取消收藏收藏状态会同步到本地缓存。详情页支持切换夜间模式切换后页面背景、文字颜色与导航栏同步变化。我的页未登录时显示默认头像与登录按钮登录后展示微信头像与昵称。我的页可查看所有已收藏的新闻点击收藏项可再次进入详情页浏览。自定义 TabBar 在首页与我的页之间切换流畅图标与文字选中态高亮。四、问题总结与体会1. 遇到的问题及解决方法问题 1自定义 TabBar 切换页面后高亮状态未同步。解决方法在每个 Tab 页面的onShow中调用this.getTabBar().setData({ selected: ... })根据页面索引更新选中态。问题 2详情页开启夜间模式后返回首页首页导航栏仍保持深色。解决方法在详情页的onHide与onUnload生命周期中若当前为夜间模式则调用wx.setNavigationBarColor恢复默认配色。问题 3使用chooseAvatar获取的头像地址为临时路径退出小程序后无法再次加载。解决方法通过wx.getFileSystemManager().saveFile将临时头像转存到wx.env.USER_DATA_PATH下获得持久化文件路径。问题 4早期版本直接以新闻id作为缓存键存储收藏导致缓存键混乱且难以批量读取。解决方法改为使用单一缓存键my_favorite_news保存收藏数组并提供增删查接口。问题 5新闻标题过长时列表卡片换行不美观。解决方法使用-webkit-line-clamp: 2对标题进行两行截断显示并保持卡片高度一致。2. 收获与体会通过本次实验我完成了一个功能较完整的高校新闻小程序主要收获如下组件化与自定义组件理解了custom-tab-bar的注册与使用方式掌握了自定义组件的生命周期与事件通信。列表渲染与数据绑定通过wx:for和wx:key实现新闻列表渲染使用data-id与bindtap完成页面传参与跳转。本地缓存的综合应用使用wx.getStorageSync/wx.setStorageSync保存登录信息、收藏列表与夜间模式偏好理解了小程序本地存储的适用场景。微信登录能力更新了解到getUserProfile获取用户信息的方式已被官方弱化学会了使用chooseAvatar与typenickname获取用户头像和昵称。页面生命周期在实践中体会了onLoad、onShow、onHide、onUnload等生命周期函数的执行时机与用途。UI 细节打磨通过圆角、阴影、flex 布局、安全区适配env(safe-area-inset-bottom)等手段提升页面视觉效果与用户体验。3. 对课程安排的建议希望后续课程能够继续深入讲解小程序的云开发能力如云数据库、云函数、状态管理方案以及如何使用主流 UI 组件库如 Vant Weapp、WeUI快速搭建复杂页面。同时期待有更多关于小程序性能优化、分包加载与多端适配的实战案例。