小程序初探(二)
iBistu 4.0终于在几位同学的努力下正式推出,我也没想到iBistu怎么就发展到了4.0,四年多过去了,还能“隐约”看到学长们的代码,这种“恍如隔世”的感觉每写下一行代码就会冒出。
在学习开发微信小程序的过程中,一直在苦于追求到底哪些项目才适合与新手小白去磨练,某天下午突然想到iBistu新闻模块的这种“不干不湿”情况正适合于练手各种前端框架(我认为小程序也是一种前端框架)
iBistu新闻模块在API文档上写的非常清楚,我们只需要传入一些参数即可获取到校内新闻的JSON数据,而对于微信小程序来说,解析JSON格式的数据是最为方便不过了。再加上iBistu 4.0简洁的UI风格,不会让我这种第一次上手前端开发的同学感到阻力很大,反而还会有一种“过五关,斩六将”的feel~😝
经过上次的小程序初探,了解了小程序的整体架构、开发要求和规范,再加上参与了iBistu 4.0的iOS端开发,预估开发成本不大且获取开发经验可观,遂,开干~
从iBistu的API文档中可以看到,想要获取新闻数据,我们需要传入category(新闻分类)、page(分页数)、api_key和session_token(login后获取)四个参数给api.iflab.org/api/v2/newsapi/newslist这个接口
其实这第一步就有点恶心了,最开始我想的是,把iBistu新闻模块单独抽出来,作为一个独立的小程序供大家使用,但是获取iBistu所有数据的前提是,你得登录!!!想了一会儿,有两种解决方案,要么在小程序上单独做一个login入口,要么就自己再搭一个后台,第一次获取用户iBistu用户名和密码后把这些数据都存下来,以后每次做网络请求发现token过期时在后台自动刷新token。
其实从开发成本上来说,我会毫不犹豫的选择第一种,这样会很快,但是给用户的体验非常不好,在iBistu端上要登录,用你这个小程序也要登录,单从开发者角度上来想就很扯,做完自己都不想用。
现目前暂定第二种方案,但是为了加速开发时间,这部分工作挪到寒假再做吧。🙂来看看最终的效果:
从完成图效果上来看,除了不能侧滑切换新闻主题外,剩余部分已经达到甚至部分细节超过了Native,而且这还是在微信开发工具里的模拟器上显示出来的效果,因为没有注册AppID,要不然就能在微信端上预览效果了。
那,为什么不注册AppID呢?因为iBistu的数据源挂在在api.iflab.org下,iflab.org并没有在国内备案,如果你在微信小程序后台注册了AppID,你就得添加可信域名,这个可信域名不但要求是添加了SSL证书还得是通过了备案的,遂,iflab.org因此GG。
不过这样也好,新闻数据因为都是开发团队里的一个学长去学校官网上爬的,学校官网本身就没有加SSL证书,通过image标签去加载拿到的imageLink还得再去小程序后台上添加一次对应的域名,加上还没SSL证书,因此也GG。_(:зゝ∠)_
这是iBistu新闻小程序的整体文件结构,就比微信小程序提供的开发模板多了四个文件而已,整个小程序总体大小为49KB(大家千万记住,小程序对开发文件大小限制在了1M以内)。
index是新闻列表页,content为列表item内容页,我们首先来拆分列表页,红色为cell中的单个标签,蓝色为一个cell
iBistu在iOS端上采取了新建两个xib来完成两种不同样式的加载只有title和什么都有的cell,但在小程序中,我们只需要一个样式就足够了,因为新闻的整体listView和每条新闻cell都采用了flex弹性布局,如果布局中的元素hidden了能够自动“弹”回去,因此,我们的index.wxml可以这么来写cell,
1 | <view class='contentView'> |
关于顶部的tab导航栏,实际上是一个水平滚动的scroll-view(小程序也提供了跟UIScrollView一样的scroll-view喔~),关于它的元素布局我们可以在index.wxml中这么写,
1 | <scroll-view class='titleHeadView' scroll-x='true'> |
这样,我们就拿到了一个搭好初步框架的新闻主体,接下来,我们去美化它。在index.wxss中可以这么写,
1 | .contentView { |
当然,wxss的样式定义是像素级copyiBistu的,如果大家觉得不好看的话,自行修改吧。现在,我们就已经把View层的东西都整理好了,接下来要做的事情就是去做网络请求拉到数据,再填充到View层中来即可。
首先来看顶部的scroll-view的数据填充,从API文档中可以看到,要求我们传入分类,而不是从一个接口取得所有新闻分类的信息,也就是说,新闻的分类信息我们要本地写死,
1 | data: { |
正式开始进行网络请求工作之前,我们还差一个也是最重要的参数未知,session_token,这个参数是用户登录后返回的字段,24小时之内未带上这个token进行请求,则失效。emmm,我的做法就是先去运行一个iBistu的Xcode工程,拿到token后再粘回来,先这么简单粗暴的做着。
对api.iflab.org/api/v2/newsapi/newslist这个接口请求数据,需要附带四个参数,拼接完的wx.request如下,
1 | // 在onLoad中写下这个函数 |
因为有几个地方需要用到api_key和token,因此我们可以把它丢入到app.js中,然后再通过使用跟上文一样的getApp().globalData即可取到全局数据(可以说跟pch文件和NSUserDefault非常类似了。)
1 | globalData: { |
此时,我们运行小程序,即可看到在控制台看到请求回来的信息。现在要把信息都展示到view上,我们需要在wxml中用到wx:for和wx:if这两个东西,补充完后的wx:request如下,
1 | wx.request({ |
补充完的index.wxml如下,
1 | <scroll-view class='titleHeadView' scroll-x='true'> |
需要注意的是,当我们使用wx:for去动态加载wxml中的标签时,在填充数据的时候要可以使用小程序提供的遍历对象item,这个item你可以认为是C++里的迭代器,通过迭代器去访问遍历到的每一个对象中的值。当然,如果你不想用它提供的item,你可以使用当前的循环遍历index,index代表了当前循环到的下标,然后通过下标去指定输出内容。
此时再次运行小程序,即可看到新闻数据和顶部的tab数据加载出来啦~~!!!我们再进一步,点击scroll-view上的tab标签切换新闻内容!想要做到这一点,首先要给tab添加点击事件,小程序提供了冒泡事件和非冒泡事件,简单来说就是一个是触摸事件可以逐层向上传递,另外一个不能,具体使用方法大家可以去看小程序开发文档,那里的讲解更加详细。在此,根据需求我给view绑定的是非冒泡事件catchtap,实现如下
1 | titleHeadViewTapClick: function (event) { |
再运行工程,可以通过点击顶部tab来切换新闻啦~!!我们再往前推进,把上拉加载也做了,因为毕竟是新闻嘛,信息流的展示还是趋于给用户“无限”的感觉。在index.json中添加enablePullDownRefresh字段,开启上拉功能,
1 | { |
因为是上拉加载,那么必定会涉及到数据的分页,也就是前文中我们所说的page字段的作用,page字段每+1,数据就会返回时间上相对之前返回的时间更早一些的数据。我们要做的效果是追加数据,注意!是追加!更新完后的整个index.js如下所示
1 | var p = 0 |
大家从上文也看到了多了一个contentViewTapClick方法,这个方法就是我们后边要展开说的内容,从API文档上我们找到新闻详情接口,需要我们传入link字段数据,这个数据是个URL,问了学长,实际上就是给这个接口丢一个让它自己去实时抓数据的地址。hhhhh,这个做法确实巧妙。因此,我们需要在点击每条新闻的wx.navigationTo跳转方法时传入link字段的数据。
在content.js中写下,
1 | onLoad: function (options) { |
运行小程序,随便点击一条新闻,就会在控制台中打印出来了相关信息。刚开始我想偷个懒,想直接navigationTo拿到的link,没想到小程序居然不支持H5外链,只能跳转自身页面,所以只能自己拼数据了。
iBistu iOS端的新闻不是我写的,对于其中的一些实现新闻详情的巧妙方法我是一点都不了解,所以看到返回来的新闻详情数据后,整个人都不好了。
我的乖乖,您看懂是什么意思了么?一堆回车符的地方就是要插入图片的地方。😱。所以我们要根据回车符出现的地方来判断是否应该插入图片,看了看iBistu的新闻详情部分的实现,确实是这么做的。
但是更伤的问题来了,根据回车符我截断字符串在数组里,然后po出了内容,一看更呆了,图片在一个地方集中出现得越多,那么这块地方的换行符也就越多,换句话说,得根据回车符的多少来决定插入的图片数量。
嗯,其实这还不是最伤的,按照这个思路弄完了以后,浏览了前面几条新闻,完美对上了,但是!!!到了后边的几条新闻就全乱了。该出现图片的地方没出现,不该出现的图片的地方空一大片
原因是因为刚开始找到的规则是,三个换行放一张图片,如果当前区域放超过一张图片,比如说是两张图片,换行数则由三个变成了七个,也就是说,以三位基数,每多加两个换行多一张图片。
但事实上不是这样啊!😭。后边几条新闻的换行数跟图片数对应关系完全不符合之前找到的,全乱了。这就非常的难受了。弄到最后,实在没办法,决定了如果是多张图片就只放一张😔。
如果这部分你没能拿到真实数据好好研究一番的话,就算看了代码意义也不太大,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 Page({
/**
* 页面的初始数据
*/
data: {
resData_cn: [],
resData_image: [],
resData_display: [],
resDataCount: 0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this
wx.showLoading({
title: '加载中',
})
wx.request({
url: 'http://api.iflab.org/api/v2/newsapi/newsdetail',
method: 'GET',
data: {
// 拿到NavigationTo拼接而来的参数
link: options.link,
api_key: getApp().globalData.api_key,
session_token: getApp().globalData.session_token
},
success: function (res) {
wx.hideLoading()
var resString = res.data.article.split('\n')
var resdata_cn = []
var resdata_cn_index = -1
var resdata_display = []
var tempIndex = 0
for (var i = 0; i < resString.length; i++) {
// 判断是否含有中文,若不含有中文则为图片
// 即换行符
if (/.*[\u4e00-\u9fa5]+.*$/.test(resString[i])) {
tempIndex = 0
resdata_cn_index++
resdata_cn[resdata_cn_index] = resString[i]
resdata_display[resdata_cn_index] = true
} else {
tempIndex++
// 这么搞新闻图片加载不全
if (tempIndex == 3) {
resdata_display[resdata_cn_index] = false
}
}
}
var count = resdata_cn.length + res.data.imgList.length
var displayArr = []
var displayIndex = 0
for (var j = 0; j < resdata_display.length; j++) {
if (resdata_display[j]) {
displayArr[j] = ""
} else {
displayArr[j] = res.data.imgList[displayIndex]
displayIndex ++
}
}
that.setData({
resData_image: displayArr,
resData_cn: resdata_cn,
resDataCount: count,
resData_display: resdata_display,
})
wx.hideLoading()
}, fail: function (res) {
}, complete: function () {
}
})
}
})
其中设置了很多BOOL变量,为啥要设置这么多的BOOL变量呢?我们来看一张图,
我对content.wxml做了如上的分割,实际上也是一个listView,每一个cell(蓝色)中都有text和image,其写法如下所示,
1 | <view> |
通过控制image标签的hidden来达到效果,这就是为什么设置了这么多BOOL变量的原因。😝
以上就是我二探小程序的历程,可能说的有些不够清晰,你可以在GitHub下载源码,自行研究一番,就能够理解我以上所讲述的东西了。
这次二刷小程序,给我的感觉是以前端上觉得做起来的简单的东西,在小程序上会越发的更加简单,在端上觉得比较困难的东西,小程序说不定会有一些比较奇妙的解法,甚至会有出其不意的地方。这两次学习小程序的开发,总的来说,让我很意外,小程序不但是给用户“用完即走”的感觉,给开发者也一身轻松,不过,也只是“小程序”。