源起
最近由于被人问起,一时间心血来潮想到写一个微信小程序,于是就捣鼓了一个超级简单的小程序:哔哩哔哩新番时间表。
开始!
我们首先需要在微信公众平台注册一个账号,然后下载它的一个开发工具:微信开发者工具。这个软件在该平台可以下载。接着打开工具,使用微信登陆后,创建一个新项目,点击使用测试号即可。如图:

了解小程序结构
这里我得感谢一下梁老师,是他强制让我们使用Node.js
开发网站,让我对于微信小程序开发有了一定的基础。微信小程序可以用Node.js开发,也能使用php,这里我们当然是用Node.js
了,因为选择的测试号,开发工具没有提供php
这个选项。好的,我们来看一下我这个小程序的目录结构:

好的,这个wxml文件和wxss文件分别对应我们常见的的html和css文件,语法都是一样的。
进入主题
我们先找到哔哩哔哩的各种API,这里我直接给出我所用到的API:
- 新番时间表:https://bangumi.bilibili.com/web_api/timeline_global
- 番剧详情:https://bangumi.bilibili.com/ext/web_api/season_count?season_id='+this.data.id+'&season_type=1,这里this.data.id对应番剧的id;
- 推荐番剧:https://api.bilibili.com/pgc/web/recommend/related/recommend?season_id= + this.data.id;
- 当前在线人数及稿件数:http://api.bilibili.com/x/web-interface/online ,这个我调用失败了,我非常确定B站对这个API做了防盗链处理!
说一下思路:请求API,分析返回的json,获取数据,传数据给wxml,wxss完成修饰效果,最后由微信完成渲染。
app.js
这是小程序的入口文件,我们直接调用API,不需要配置它。
app.json
这里配置小程序的名称,目录,颜色样式等等,代码如下:
{ "pages": [ "pages/index/index", "pages/detail/detail" ], "window": { "backgroundTextStyle": "dark", "navigationBarBackgroundColor": "#2196f3", "navigationBarTitleText": "哔哩哔哩新番时间表", "navigationBarTextStyle": "white", "enablePullDownRefresh": true } }
|
现在我们来到index文件夹
index.js
这个文件定义的是主页的监听操作,如下:
Page({ data: { setall:[], detail:[] },
onLoad: function (options) {
},
onReady: function () {
},
onShow: function () { this.getstart() },
onHide: function () {
},
onUnload: function () {
},
onPullDownRefresh: function () {
},
onReachBottom: function () {
}, getstart(){ wx.request({ url: 'https://bangumi.bilibili.com/web_api/timeline_global', success:(res) => { this.setData({ setall:res.data.result }) } }) },
goToDetail(e){ wx.navigateTo({ url: '/pages/detail/detail?id='+e.target.dataset.id }) }
})
|
我们需要使用Page({})将整个文件涵盖,wx.request({})是请求一个url,然后会有一个response,我们就从这个response取数据。wx.navigateTo({})是和bindtap跳转结合使用的,在index.wxml中会提到。
index.wxml
这里就相当于html格式,先给出代码:
<view id="stories-list" bindtap="goToDetail"> <block wx:for="{{ setall }}" wx:key="item.date_ts"> <view id="time"> <text id="date">{{item.date}}号更新番剧:</text> <block wx:for="{{item.seasons}}" wx:key="stories.ep_id" wx:for-item="stories"> <view id="detail" data-id="{{stories.season_id}}"> <text id="{{stories.season_id}}" data-id="{{stories.season_id}}">{{stories.title}}{{stories.pub_index}}\n更新时间:{{stories.pub_time}}\n追番人数:{{stories.favorites}}人</text> <image src="{{ stories.square_cover }}" data-id="{{stories.season_id}}"></image> </view> </block> </view> </block> </view>
|
我们在index.js中定义了一个数组:setall,我们使用wx:for=”“来遍历它,这里<view>就相当于<div>标签。wx:key=”item.data_ts”(指定遍历唯一标识)是因为我们可以发现每一个数组中的元素的data_ts都是不同的,所以可以作为唯一标识(key)。这里的data_ts是请求了https://bangumi.bilibili.com/web_api/timeline_global 得到的response里的数据,不是凭空捏造的。这里的item代替了setall,相当于setall变成了item(换了个名字,小程序语法要求)如图:

我们在index.js使用了代码:
如此,我们就能得到外层数据,因为我们发现这里的response存在双重嵌套(可以自己访问这个API链接详细观察)。这么一来,我们就需要换名了。我们先使用item.seasons这个数组来循环,接着使用wx-for-item=”stories”将循环数组换成stories这个名字,接下来我们就能欢快地使用它得到某一天所有的更新番剧啦!接着由于我们使用了bindtap=”goToDetail”,需要为后端传一个番剧的id,来构造该番剧的链接,使用data-id=”“,便能在我们点击其所属标签域时把id值传回给后端。比如我们这里给img,text加上了data-id,如果只在text加上了data-id,那我们点击图片,就不会把id值传回给后端。我们在goToDetail()函数里使用e.target.dataset.id得到id值。
index.wxss
这个就相当于css,我这里用了弹性布局,显示效果好一点:
#date{ font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; } #detail { display: flex; padding: 20rpx; border-radius: 10rpx; margin: 20rpx 0; background: white; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); }
#detail text { display: block; flex-grow: 1; font-size: 27rpx; margin-right: 30rpx; }
#detail image { width: 120rpx; height: 120rpx; }
|
这个我就不多解释了,只要能正确得到数据,效果什么的永远也不慌。但是rpx=0.5px,这个得了解一下。
index.json
这个没什么好说的,基本没用到。
现在来到detail文件夹
detail.js
老办法,首先确定需要的变量,然后方法和index.js基本一样:
Page({ data: { id: '', coins:'', danmakus:'', views:'', detail:[] }, onLoad(option) { if (option.id || option.query.id) { this.data.id = option.id || option.query.id; } }, onShow() { this.getDetail() },
getDetail() { wx.request({ url: 'https://bangumi.bilibili.com/ext/web_api/season_count?season_id='+this.data.id+'&season_type=1', success: (res) => { this.setData({ coins: res.data.result.coins, danmakus: res.data.result.danmakus, views: res.data.result.views }), this.getRecommend() } }) }, getRecommend(){ wx.request({ url: 'https://api.bilibili.com/pgc/web/recommend/related/recommend?season_id=' + this.data.id, success: (res) => { this.setData({ detail:res.data.result }) } }) } })
|
我们得注意一下获取id的方法!
index.wxml
<view id="top">
<text>该番剧当前硬币总数:{{coins}};\n</text> <text>当前弹幕总数:{{danmakus}};\n</text> <text>当前播放总数:{{views}};\n</text> </view> <view id="comicRe"> <text id>为您推荐以下番剧:</text> </view> <view id="recommend" wx:for="{{detail}}" wx:key="season_id"> <text id="{{item.season_id}}"> {{item.title}}{{item.new_ep.index_show}} </text> <image src="{{item.cover}}"></image> </view >
|
有了以上的经验,相信这里的单循环比较简单了。
detail.wxss
#recommend { display: flex; padding: 20rpx; border-radius: 10rpx; margin: 20rpx 0; background: white; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); }
#recommend text { display: block; flex-grow: 1; font-size: 27rpx; margin-right: 30rpx; }
#recommend image { width: 120rpx; height: 120rpx; }
#top { display:flex; padding: 20rpx; border-radius: 10rpx; margin: 20rpx 0; background: white; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); }
#top text { display: block; flex-grow: 1; font-size: 27rpx; margin-right: 30rpx; }
#comicRe { display:flex; padding: 20rpx; border-radius: 10rpx; margin: 20rpx 0; background: white; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); }
#comicRe text { display: block; flex-grow: 1; font-size: 27rpx; margin-right: 30rpx; }
|
这里一样的布局方式。
detail.json
和index.json一样,用不上。
让我们看一看效果!
我们最好使用ipnone6测试小程序,测试效果如下:

本来还想加入其它功能的,结果B站的API不公开。全得自己F12找,而且它的数据不是API能够得到的,于是就没办法做了。希望我以后能做出更多更好玩的小程序吧,现在事情还有点多。