2022年夏季《移动软件开发》实验报告
一、实验目标
1.完成新闻小程序
二、实验步骤
列出实验的关键步骤、代码解析、截图。
1.准备工作
实验文档了提供 common.js、图片文件、以及 index 页面的代码,下载地址:https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/demo4_file.zip
本次实验还需要创建其他自定义文件,需要创建以下两个文件夹:
images:存放图片素材
utils:用于存放js文件
这些都可以通过前面给的下载地址解压获得,并且已经编写好了部分代码。
配置完成后目录结构如下图所示
2.视图设计
2.1导航栏设计
更改app.json,实现导航栏文本和导航栏的颜色效果。
文件代码如下:
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#328EEB",
"navigationBarTitleText": "高校新闻网",
"navigationBarTextStyle": "whitek"
}
2.2tarbar设计
我们需要在app.json中追加tarbar相关属性的代码,更新后app.json如下:
"tabBar": {
"color":"#000",
"selectedColor": "#328EEB",
"list":[
{
"pagePath":"pages/index/index",
"iconPath":"images/index.png",
"selectedIconPath":"images/index_blue.png",
"text":"首页"
},
{
"pagePath":"pages/my/my",
"iconPath":"images/my.png",
"selectedIconPath":"images/my_blue.png",
"text":"我的"
}
]
},
完成效果如下:
2.3页面设计
2.3.1首页设计
我们需要设计一个如下图所示的页面。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jGGzbTm8-1661214706156)(C:\Users\yuan\AppData\Roaming\Typora\typora-user-images\image-20220821090856025.png)]
主要包含了2个区域,这两个区域我们需要摆放:
区域1:幻灯片播放,使用swiper组件,滚动播放
区域2:view容器,内部使用数组循环
index.wxml代码如下:
<!--幻灯片滚动-->
<swiper indicator-dots autoplay interval="5000" duration"500" ></swiper>
<!--新闻列表-->
<view id= "news-list">这是新闻列表</view>
接着为组件添加wx:for,使其能够循环展示我们的图片。
<!--幻灯片滚动-->
<swiper indicator-dots="true" autoplay="true" interval="5000" duration="500">
<block wx:for="{{swiperImg}}" wx:key='swiper{{index}}'>
<swiper-item>
<image src="{{item.src}}"></image>
</swiper-item>
</block>
</swiper>
<!--新闻列表-->
<view id='news-list'>
<view class='list-item' wx:for="{{newsList}}" wx:for-item="news" wx:key="{{news.id}}">
<image src='{{news.poster}}'></image>
<text data-id='{{news.id}}'>◇{{news.title}}——{{news.add_date}}</text>
</view>
</view>
相关的wxss设计如下:
/*新闻列表区域样式*/
/*2-1新闻列表容器*/
#news-list {
min-height: 600rpx;
padding: 15rpx;
}
/*2-2列表项目*/
.list-item{
display: flex;
flex-direction: row;
border-bottom: 1rpx solid gray;
}
/*2-3新闻图片*/
.list-item image{
width:230rpx;
height: 150rpx;
margin: 10rpx;
}
/*2-4新闻标题*/
.list-item text{
width: 100%;
line-height: 60rpx;
font-size: 10pt;
}
为了进行预览,需要在js的data中临时录入一些测试数据,代码如下:
data: {
//幻灯片素材
swiperImg: [
{src: 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage1.jpg'},
{src: 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage2.jpg'},
{src: 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage3.jpg'}
],
//临时新闻数据
newsList:[
{
id:'264698',
title:'***',
poster:'http://www.ahnu.edu.cn/__local/A/C7/68/C2C9E5E2161A466A2D54D21A63C_DD2FEC40_4EBBB.jpg?e=.jpg',
add_date:'2018-03-05'
}
]
},
2.3.2个人中心页设计
个人中心页面主要包含了两个板块,即登录面板和我的收藏
界面设计如下:
其中登录面板用于显示用户微信头像和昵称,我的收藏用于显示收藏的本地新闻列表。
计划使用view组件进行整体布局,对自定义id名称解释如下:
myLogin:登录面板
myIcon:微信头像图片
nickName:微信昵称
myFavorites:我的收藏
添加后的my.wxml代码如下:
<!--登录面板-->
<view id = "myLogin" >
<block>
<image id = 'myIcon' src="{{src}}" ></image>
<text id ='nickName'>{{nickName}}</text>
</block>
</view>
<!--我的收藏-->
<view id='myFavorites' >
<text >我的收藏</text>
<!--收藏的新闻列表-->
<view id ='news-list'>
<view class='list-item' wx:for -item = "news" wx:key = "{{news.id}}">
<image src="{{news.poster}}"></image>
<text>◇{{news.title}} -- {{news.add_date}}</text>
</view>
</view>
</view>
同时美化样式,又注意到其实新闻列表样式和首页相同,故复用代码减少冗余,把index.wxss中新闻列表样式代码移动到app.wxss的公共中使用。
添加my.wxss代码如下:
#myLogin{
background-color: #328EEB;
height: 400rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
#myIcon{
width: 200rpx;
height: 200rpx;
border-radius: 50%;
}
#nickName{
color:white;
}
#myFavorite{
padding: 20rpx;
}
添加(包括index.wxss移动到app.wxss,app.wxss代码如下)
/*2-1新闻列表容器*/
#news-list {
min-height: 600rpx;
padding: 15rpx;
}
/*2-2列表项目*/
.list-item{
display: flex;
flex-direction: row;
border-bottom: 1 rpx solid gray;
}
/*2-3新闻图片*/
.list-item image{
width:20rpx;
height:150rpx;
margin:10rpx;
}
/*2-4新闻标题*/
.list-item text{
width:100%;
display: block;
line-height: 60rpx;
font: size 10pt;
}
我们可以在common.js里找一条代码替换my.js中的data
data: {
nickName:'未登录',
src:'/images/index.png',
newsList:{id: '264698',
title: '省退役军人事务厅来校交流对接工作',
poster: 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage1.jpg',
content: ' 8月19日,省退役军人事务厅二级巡视员蔡元和、办公室主任刘恒贵、就业创业处副处长钟俊武一行来校就联合共建安徽退役军人学院事宜进行交流对接。校党委常委、副校长陆林,芜湖市退役军人事务局党组成员、副局长张桂芬,学校办公室、人事处、教务处、招就处、学生处、研究生院、体育学院负责同志参加会议。',
add_date: '2022-08-19'},
},
2.3.3新闻页设计
新闻页面是用于给用户浏览新闻全文的,首先需要用户点击首页的新闻列表,然后再新窗口打开该页面。新闻页包括了新闻标题,新闻图片,新闻正文和新闻日期,页面设计如下所示:
由于没有做跳转,我们需要在程序编译的时候直接进入该界面以便调试。在微信开发者工具的顶端工具栏找到普通编译下拉选项,选择添加编译模式,然后追加对于detail界面的直接预览效果。
使用view组件进行整体的布局,对自定义的class名称解释如下:
container:整体容器
title:新闻标题区域
poster:新闻图片区域
content:新闻正文区域
add_date:新闻日期区域
编写detail.wxml代码如下:
<view class="container">
<view class="title">{{article.title}}</view>
<view class="poster">
<image src="{{article.poster}}" mode="widthFix"></image>
</view>
<view class = "content">{{article.content}}</view>
<view class = "add_date">时间:{{article.add_date}}</view>
</view>
detail.wxss如下:
/*整体容器*/
.container{
padding: 15rpx;
text-align: cneter;
}
/*新闻标题*/
.title{
font-size: 14pt;
line-height: 80rpx;
}
/*新闻图片*/
.poster image{
width: 700px;
}
/*新闻正文*/
.content{
text-align: center;
font-size: 12pt;
line-height: 60rpx;
}
/*新闻日期*/
.add_date{
font-size:12pt;
text-align: right;
line-height: 30rpx;
margin-right: 25rpx;
margin-top: 20rpx;
}
为了预览,我们可以在detail.js文件的data里面临时录入测试数据
data: {
article:{id: '264698',
title: '省退役军人事务厅来校交流对接工作',
poster: 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage1.jpg',
content: ' 8月19日,省退役军人事务厅二级巡视员蔡元和、办公室主任刘恒贵、就业创业处副处长钟俊武一行来校就联合共建安徽退役军人学院事宜进行交流对接。校党委常委、副校长陆林,芜湖市退役军人事务局党组成员、副局长张桂芬,学校办公室、人事处、教务处、招就处、学生处、研究生院、体育学院负责同志参加会议。',
add_date: '2022-08-19'},
},
基本页面布局和测试都已经完成,我们开始逻辑编写了。
2.4逻辑设计
2.4.1公共逻辑
使用提供的common.js即可。在common.js添加getNewList 和 getNewsDetail 函数,分别用于获取新闻列表信息和指定id的新闻内容。
代码如下(common.js已经写好了,以下是common.js中的函数实现):
//获取新闻列表
function getNewsList() {
let list = [];
for (var i = 0; i < news.length; i++) {
let obj = {};
obj.id = news[i].id;
obj.poster = news[i].poster;
obj.add_date = news[i].add_date;
obj.title = news[i].title;
list.push(obj);
}
return list; //返回新闻列表
}
//获取新闻内容
function getNewsDetail(newsID) {
let msg = {
code: '404', //没有对应的新闻
news: {}
};
for (var i = 0; i < news.length; i++) {
if (newsID == news[i].id) { //匹配新闻id编号
msg.code = '200'; //成功
msg.news = news[i]; //更新当前新闻内容
break;
}
}
return msg; //返回查找结果
}
// 对外暴露接口
module.exports = {
getNewsList: getNewsList,
getNewsDetail: getNewsDetail
}
2.4.2首页逻辑设计
首页逻辑主要有两个,一个是展示新闻列表,还有一个是点击标题可以跳转对应的内容页面。
首先是新闻列表,在index.js下添加onload函数,在启动时就获取新闻的列表,放入newsList中。
onLoad: function(options) {
//获取新闻列表
let list = common.getNewsList()
//更新列表数据
this.setData({
newsList: list
})
},
然后是希望用户点击新闻标题就可以跳转,在index.wxml中更改如下:
<!--新闻列表-->
<view id='news-list'>
<view class='list-item' wx:for="{{newsList}}" wx:for-item="news" wx:key="{{news.id}}">
<image src='{{news.poster}}'></image>
<text bindtap='goToDetail' data-id='{{news.id}}'>◇{{news.title}}——{{news.add_date}}</text>
</view>
</view>
添加了点击跳转的事件,点击文本后将会执行gotodetail函数.
对应的js文件也要做一定的修改,如下:
goToDetail: function(e) {
//获取携带的data-id数据
let id = e.currentTarget.dataset.id;
//携带新闻id进行页面跳转
wx.navigateTo({
url: '../detail/detail?id=' + id
})
},
这样我们首页逻辑基本完成了
2.4.3新闻页逻辑
新闻页的逻辑主要有显示对应的新闻以及可以添加或者取消新闻的收藏
我们在details页面的js文件编写获取新闻的逻辑,代码如下:
onLoad(options) {
let id = options.id
let result = common.getNewsDetail(id)
if (result.code =='200')
this.setData({
article:result.news
})
},
通过common.js写好的函数来获取结果文件,如果获取成功则写入data。
接下来我们需要增添 添加取消新闻收藏的功能
这需要我们相对detal.wxml代码进行修改,添加对于新闻添加和取消收藏的两个按钮。
编写html代码如下:
<view class="container">
<view class="title">{{article.title}}</view>
<view class="poster">
<image src="{{article.poster}}" mode="widthFix"></image>
</view>
<view class = "content">{{article.content}}</view>
<view class = "add_date">时间:{{article.add_date}}</view>
<button wx:if ='{{isAdd}}' plain bindtap="cancelFavorites">已收藏</button>
<button wx:else ='{{isAdd}}' plain bindtap="addFavorites">点击收藏</button>
</view>
相应的js代码如下:
onLoad(options) {
let id = options.id
var article= wx.getStorageSync(id)
if (article!=''){
this.setData({
article:article,
idAdd:True
})
}
else{
let result = common.getNewsDetail(id)
if (result.code =='200')
this.setData({
article:result.news,
isAdd:False
})
}
},
添加了if else分支,如果能从内存中读到对应id的文章,那么认为已经被收藏;反之亦然。
同时继续在js文件支架addFavorites函数和cancelFavorites函数。
如下:
addFavorites:function(options){
let article = this.data.article
wx.setStorageSync(article.id, article)
this.setData({
isAdd:True
})
},
cancelFavorites:function(options){
let article = this.data.article
wx.removeStorageSync(article.id)
this.setData({
isAdd:False
})
},
2.4.4个人中心页面逻辑
首先分析下,个人中心页需要实现三个功能,第一个是获取微信用户的信息,这个我们在第一个实验其实已经完成了;然后是获取收藏的列表,三是浏览收藏的新闻。
首先来完成获取微信用户信息
修改my.wxml代码,添加一个按钮作为登录按钮,利用wx:if逻辑来实现未登录时显示按钮,登录了只显示头像和昵称。并且给这个按钮绑定一个点击事件进行登录。
代码如下:
<view id = "myLogin" >
<block wx:if ="{{isLogin}}">
<image id = 'myIcon' src="{{src}}" ></image>
<text id ='nickName'>{{nickName}}</text>
</block>
<button wx:else open-type="getUserInfo" bindgetuserinfo="getMyInfo" >未登录,点击此处登录</button>
</view>
并且添加getMyInfo函数,如下:(my.js)
getMyInfo:function(e){
let info = e.detail.info
this.setData({
isLogin:true, //确认登录状态
src:info.avataUrl, //图片来源
nickName:info.nickName //微信昵称
})
},
效果如下:
接下来是获取收藏列表了
修改wxml代码,将我的收藏后面数字改为动态的。
<text >我的收藏{{num}}</text>
并把data中添加num:0元素。
再修改js逻辑,主要为追加getMyFavorites函数,如下:
getMyFavorites:function(){
let info = wx.getStorageInfoSync()
let keys = info.keys
let num = keys.length
let myList = []
for (var i =0 ; i< num ;++i){
let obj = wx.getStorageSync(keys[i])
myList.push(obj)
}
this.setData({
newsList:myList,
num:num
})
},
修改getMyInfo函数如下,增加获取收藏列表:
getMyInfo:function(e){
let info = e.detail.userInfo
this.setData({
isLogin:true, //确认登录状态
src:info.avatarUrl, //图片来源
nickName:info.nickName, //微信昵称
myList:myList,
num:num,
})
this.getMyFavorites()
},
为实现用户手动更改新闻的状态需要刷新列表,我们在onShow函数中修改代码:
onShow() {
if(this.data.isLogin){
this.getMyFavorites()
}
},
最后是实现浏览收藏的新闻
修改my.wxml如下:
<!--收藏的新闻列表-->
<view id ='news-list'>
<view class='list-item' wx:for-item = "news" wx:key = "{{news.id}}">
<image src="{{news.poster}}"></image>
<text bindtap="goToDetail" data-id = "{{news.id}}">◇{{news.title}} -- {{news.add_date}}</text>
</view>
</view>
增加goToDetail 函数,my.js代码如下:
goToDetail:function(e){
let id = e.currentTarget.dataset.id
wx.navigateTo({
url: '../detail/detail?id=' + id
})
},
这样我们就完成啦(记得去掉我们的测试数据)
三、程序运行结果
单机我的收藏的列表后,可以正常跳转至正确的detail页面
四、问题总结与体会
遇到的问题
无法跳转到detail页面,经过排查是自己修改了文件夹名称但未修改app.json的page路径
心得体会
这次的微信小程序实验体量较以往较大,但作出来的效果也初具一个普通小程序该有的雏形,也让我更加了解了微信小程序运行的逻辑。但仅仅只看文档是远远不够的,需要自己去查找资料,比如onshow函数是监听每个界面的,以此实现更改登录状态能够自动刷新出自己收藏列表的效果。
wx.navigateTo({
url: '../detail/detail?id=' + id
})
},
这样我们就完成啦(记得去掉我们的测试数据)
三、程序运行结果
<img src="C:\Users\yuan\AppData\Roaming\Typora\typora-user-images\image-20220822235014228.png" alt="image-20220822235014228" style="zoom:50%;" />
单机我的收藏的列表后,可以正常跳转至正确的detail页面
<img src="C:\Users\yuan\AppData\Roaming\Typora\typora-user-images\image-20220823081839037.png" alt="image-20220823081839037" style="zoom:50%;" />
## 四、问题总结与体会
#### 遇到的问题
无法跳转到detail页面,经过排查是自己修改了文件夹名称但未修改app.json的page路径
#### 心得体会
这次的微信小程序实验体量较以往较大,但作出来的效果也初具一个普通小程序该有的雏形,也让我更加了解了微信小程序运行的逻辑。但仅仅只看文档是远远不够的,需要自己去查找资料,比如onshow函数是监听每个界面的,以此实现更改登录状态能够自动刷新出自己收藏列表的效果。