开发一个微信小程序(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() {

  }
})

代码说明:

  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;
}

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

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>

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

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

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

 
 

 

posted @ 2022-06-09 16:41  我是冰霜  阅读(175)  评论(0编辑  收藏  举报