开发一个微信小程序(2):编写博客园随笔列表

时间:2023-01-12 17:58:51

上一篇介绍了如何通过博客园官方api获取随笔列表,本篇来实现把文章展示到小程序中

 

先来看一下最终的效果

开发一个微信小程序(2):编写博客园随笔列表

1、调用获取 access_token 接口

如果想在小程序中成功调用接口,需要在小程序后台配置服务器域名,具体位置如下

​开发/开发管理/开发设置/服务器域名​

添加接口request合法域名

开发一个微信小程序(2):编写博客园随笔列表

首先我们需要拿到个人博客园的 access_token,这里我希望不要频繁调用这个接口,当进入小程序时调用一次就够了

所以可以在​​app.js​​中写一个方法,调用接口拿到token,把token存储到内存中,后面想用的时候直接从内存中拿即可

 

打开小程序根目录下的 ​​app.js​

开发一个微信小程序(2):编写博客园随笔列表

在 ​​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、编写文章列表页面

这里要做的有如下几件事:

  • 调用博客园随笔列表接口,拿到个人的随笔数据;
  • 把列表数据渲染到前端;
  • 上拉页面加载下一页数据,下拉页面刷新数据;
  • 调整列表样式;
  • 向随笔详情页传递一些必要参数;

在开始前,先创建2个page,一个是随笔列表,一个是随笔详情

打开小程序根目录下的 ​​app.json​​​,在 ​​pages​​​ 中增加如下2个路径,保存后,会在​​pages​​​目录下自动创建对应的文件夹:一个​​article​​​,一个​​article_detial​

 

开发一个微信小程序(2):编写博客园随笔列表

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() {

}
})

代码说明:

  1. ​getPosts() ​​方法中调用博客园随笔列表接口,并把结果赋给posts参数;
  2. 在 ​​onLoad()函数​​​中调用​​getPosts() 方法​​,这样一进入这个列表页就会触发请求获取随笔数据;
  3. 在​​onPullDownRefresh()函数​​​中编写下拉刷新的代码逻辑,在这里面也要调用​​getPosts()方法​​,但是在请求前把参数重置了一下;
  4. 在​​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;
}

这样博客园随笔列表的页面就基本完成了

开发一个微信小程序(2):编写博客园随笔列表

3、文章详情页

完成博客随笔列表页面后,接下来希望点击文章能够跳转到对应的详情页

 

在上一步中,利用​​<navigator>​​标签进行页面导航,在跳转时,设置了要传递的参数

开发一个微信小程序(2):编写博客园随笔列表

在文章详情页需要接收传递来的参数

打开 ​​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>

结果发现不能显示文章详情

后来查了一下,这是微信小程序的限制,个人类型的小程序不能配置外部业务域名,所以也就无法展示外部链接的内容。。。

开发一个微信小程序(2):编写博客园随笔列表

所以退而求其次,我只在详情页展示了文章详情链接,后续再想办法如何展示文章内容

开发一个微信小程序(2):编写博客园随笔列表