微信小程序:哔哩哔哩新番时间表

源起

最近由于被人问起,一时间心血来潮想到写一个微信小程序,于是就捣鼓了一个超级简单的小程序:哔哩哔哩新番时间表。

开始!

我们首先需要在微信公众平台注册一个账号,然后下载它的一个开发工具:微信开发者工具。这个软件在该平台可以下载。接着打开工具,使用微信登陆后,创建一个新项目,点击使用测试号即可。如图:
开始

了解小程序结构

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

进入主题

我们先找到哔哩哔哩的各种API,这里我直接给出我所用到的API:

  1. 新番时间表:https://bangumi.bilibili.com/web_api/timeline_global
  2. 番剧详情:https://bangumi.bilibili.com/ext/web_api/season_count?season_id='+this.data.id+'&season_type=1,这里this.data.id对应番剧的id;
  3. 推荐番剧:https://api.bilibili.com/pgc/web/recommend/related/recommend?season_id= + this.data.id;
  4. 当前在线人数及稿件数: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格式,先给出代码:

<!--pages/index/index.wxml-->
<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(换了个名字,小程序语法要求)如图:
response
我们在index.js使用了代码:

setall:res.data.result /*取得上图中的result赋给setall*/

如此,我们就能得到外层数据,因为我们发现这里的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,我这里用了弹性布局,显示效果好一点:

/* pages/index/index.wxss */
#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

{
"usingComponents": {}
}

这个没什么好说的,基本没用到。

现在来到detail文件夹

detail.js

老办法,首先确定需要的变量,然后方法和index.js基本一样:

Page({
data: {
id: '',
coins:'',
danmakus:'',
views:'',
detail:[]
},
onLoad(option) { /*这里获取传过来的id*/
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

<!--pages/detail/detail.wxml-->
<view id="top">
<!--<text>当前B站最新投稿:{{sub}}件;\n</text>
<text>当前B站在线总人数:{{online}};\n</text> API无法访问-->
<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

/* pages/detail/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能够得到的,于是就没办法做了。希望我以后能做出更多更好玩的小程序吧,现在事情还有点多。

文章作者: Leaflag
文章链接: https://www.leaflag.cn/2019/03/12/微信小程序/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LeaflagのBlog