开发一个微信小程序(2):编写博客园随笔列表
上一篇介绍了如何通过博客园官方api获取随笔列表,本篇来实现把文章展示到小程序中
先来看一下最终的效果
1、调用获取 access_token 接口
如果想在小程序中成功调用接口,需要在小程序后台配置服务器域名,具体位置如下
开发/开发管理/开发设置/服务器域名
添加接口request合法域名
首先我们需要拿到个人博客园的 access_token,这里我希望不要频繁调用这个接口,当进入小程序时调用一次就够了
所以可以在app.js
中写一个方法,调用接口拿到token,把token存储到内存中,后面想用的时候直接从内存中拿即可
打开小程序根目录下的 app.js
在 onLaunch()
下编辑如下代码,主要是调用 api 接口
// app.js
App({
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 获取博客园token
wx.request({
url: 'https://oauth.cnblogs.com/connect/token',
method: 'POST',
header: {
'Content-Type': "application/x-www-form-urlencoded"
},
data: {
client_id: '5dd267da-xxx-xxx-xxx-xxx',
client_secret: 'eK_xxxskexxDet70aBugHCxxxa8-vU4ZWxxxA4ypPxxx2SfE',
grant_type: 'client_credentials'
},
success: (res) => { // 请求成功之后的回调函数
// console.log(res);
// wx.setStorage({ // 异步设置缓存
// key: 'access_token',
// data: res.data.access_token
// })
wx.setStorageSync('access_token', res.data.access_token) //同步获取设置缓存
var value = wx.getStorageSync('access_token') // 提取缓存中的access_token
console.log(value);
}
})
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
},
globalData: {
userInfo: null
}
})
重新编译程序,即可打印出拿到的 access_token
2、编写文章列表页面
这里要做的有如下几件事:
- 调用博客园随笔列表接口,拿到个人的随笔数据;
- 把列表数据渲染到前端;
- 上拉页面加载下一页数据,下拉页面刷新数据;
- 调整列表样式;
- 向随笔详情页传递一些必要参数;
在开始前,先创建2个page,一个是随笔列表,一个是随笔详情
打开小程序根目录下的 app.json
,在 pages
中增加如下2个路径,保存后,会在pages
目录下自动创建对应的文件夹:一个article
,一个article_detial
2.1 调用博客园随笔列表接口,拿到个人的随笔数据
打开 pages/article/article.js
,编辑如下代码
// pages/article/article.js
Page({
/**
* 页面的初始数据
*/
data: {
blogApp: 'hanmk', //博客名称参数
postCount: 0, //博客数量
isNull: false,
posts: [], // 博客园数据
isloading: false, //定一个标识符,默认为false,表示当前没有发送请求
page: 1 //获取随笔列表时需要传的页码,默认为第一页
},
// 获取博客总数
getBlogCount() {
wx.request({
url: `https://api.cnblogs.com/api/blogs/${this.data.blogApp}`,
//如果想在url中拼接字段,需要使用``包裹url
header: {
'Authorization': 'bearer ' + wx.getStorageSync('access_token')
},
method: 'GET',
success: (res) => {
console.log(res);
this.setData({
postCount: res.data.postCount
})
},
})
},
// 获取博客园随笔列表
getPosts() {
//开始发起请求时,将isloading置为true
this.setData({
isloading: true //为true时,表示正在发起请求
})
//展示loading效果
wx.showLoading({
title: '努力加载中...',
})
//发起请求
wx.request({
url: `https://api.cnblogs.com/api/blogs/${this.data.blogApp}/posts`,
header: {
'Authorization': 'bearer ' + wx.getStorageSync('access_token')
},
method: 'GET',
data: {
pageIndex: this.data.page
},
success: (res) => {
// console.log(res);
console.log(res.data);
this.setData({
posts: [...this.data.posts, ...res.data] //使用展开运算符,将旧数据取出和这次请求到的新数据拼接到一起再赋给posts(如果直接把res.data赋给posts,则始终只有请求到的数据,不会展示所有请求到的数据)
})
if (res.data.length == 0) {
this.setData({
isNull: true
})
}
},
complete: () => {
wx.hideLoading() //隐藏loading效果
//请求发起后,将isloading置为false
this.setData({
isloading: false
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.getBlogCount()
this.getPosts()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
wx.setNavigationBarTitle({
title: '冰霜博客园随笔', //把这个页面的标题自定义设置一下
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
//请求前,需要重置参数
this.setData({
page: 1,
posts: [],
postCount: 0
})
this.getPosts() //下拉刷新调用这个函数,重新发起请求
wx.stopPullDownRefresh() //真机上,刷新完后,调用这个方法,关闭下拉刷新
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
// console.log("上拉触底");
console.log(this.data.posts.length);
console.log(this.data.isNull);
if(this.data.isNull) { //如果isNull为true则弹出提示,不再发起请求
return wx.showToast({
title: '数据加载完毕!',
icon: 'none'
})
}
if(this.data.isloading) return //如果isloading为true,则退出onReachBottom这个方法
this.setData({
page: this.data.page + 1 //上拉触底时,给页码加1,这样再发起请求时,就请求到了下一页的数据
})
this.getPosts() //调用获取随笔的方法
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
代码说明:
getPosts()
方法中调用博客园随笔列表接口,并把结果赋给posts参数;- 在
onLoad()函数
中调用getPosts() 方法
,这样一进入这个列表页就会触发请求获取随笔数据; - 在
onPullDownRefresh()函数
中编写下拉刷新的代码逻辑,在这里面也要调用getPosts()方法
,但是在请求前把参数重置了一下; - 在
onReachBottom()函
数中定义上拉触底的代码逻辑,调用getPosts()方法
,每次触发请求前,给page
参数+1,也就是请求下一页的数据;
2.2 渲染数据到前端
后端拿到数据后,接下来要把数据渲染到前端
在article.js中,我用 posts
来接收接口返回的随笔数据,在前端可以使用for循环处理数据,同时为了可以点击每条随笔跳转到详情页,使用<navigator>
标签,
打开pages/article/article.wxml
代码如下
<!--pages/article/article.wxml-->
<!-- 文章列表 -->
<view class="box">
<navigator wx:for="{{posts}}" wx:key="Id" class="item"
url="/pages/article_detail/article_detail?url={{item.Url}}&auther={{item.Author}}"
open-type="navigate">
<view>
<text class="title">{{item.Title}}</text>
</view>
<view class="bottom-element">
<text class="little-text">阅读:({{item.ViewCount}}) 评论:({{item.CommentCount}})</text>
<text class="post-date">{{tools.splitDate(item.PostDate)}}</text>
</view>
</navigator>
</view>
<!-- <text>123</text> -->
<!-- <view class="box"></view> -->
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
在上述代码中,每篇博客文章都提取了如下4个属性
文章标题Title
、阅读量ViewCount
、评论数CommentCount
、发布日期PostDate
同时在跳转至具体文章详情时,传递了2个参数文章链接Url
、文章作者Author
对应的样式代码,打开pages/article/article.wxss
/* pages/article/article.wxss */
/* .box {
height: 2000rpx;
background-color: lightblue;
} */
/* 设置整个页面的背景颜色 */
page{
background-color: rgb(238, 237, 237);
}
.item {
height: 150rpx;
border-bottom: 15rpx solid #efefef;
/* border-radius: 8rpx; */
line-height: 50rpx;
/* margin: 10rpx; */
position: relative;
padding-top: 20rpx;
background-color: rgb(255, 255, 255); /*设置每张小卡片的颜色*/
}
.title{
margin-left: 20rpx;
margin-right: 20rpx;
display: -webkit-box; /*设置为弹性盒子*/
overflow:hidden; /*超出隐藏*/
text-overflow: ellipsis; /*显示省略号*/
-webkit-line-clamp: 1; /*多少行后显示省略号,这里设置为第一行超出后显示省略号*/
word-break:break-all; /*强制英文单词自动换行,可要可不要*/
-webkit-box-orient: vertical; /* 从上到下垂直排列子元素*/
}
.bottom-element{
font-size: 24rpx;
display: flex;
position: relative;
padding-top: 40rpx;
}
.bottom-element .little-text{
position: absolute;
left: 20rpx;
}
.bottom-element .post-date{
position: absolute;
right: 16rpx;
}
这样博客园随笔列表的页面就基本完成了
3、文章详情页
完成博客随笔列表页面后,接下来希望点击文章能够跳转到对应的详情页
在上一步中,利用<navigator>
标签进行页面导航,在跳转时,设置了要传递的参数
在文章详情页需要接收传递来的参数
打开 pages/article_detail/article_detail.js
,编辑代码
在 onLoad()
函数中处理传递过来的参数
// pages/article_detail/article_detail.js
//随笔详情
Page({
/**
* 页面的初始数据
*/
data: {
query: {} // 接收navigator传来的参数
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
query: options //把navigator传来的参数赋给query
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
wx.setNavigationBarTitle({
title: '随笔详情', //把这个页面的标题自定义设置一下
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
开始我文章详情的url传到详情页,然后尝试使用<web-view>
标签来展示
打开 pages/article_detail/article_detail.wxml
<web-view src="{{query.url}}"></web-view>
结果发现不能显示文章详情
后来查了一下,这是微信小程序的限制,个人类型的小程序不能配置外部业务域名,所以也就无法展示外部链接的内容。。。
所以退而求其次,我只在详情页展示了文章详情链接,后续再想办法如何展示文章内容