开发一个微信小程序(3):编写公众号文章列表

本篇讲一下如何把微信公众号中发布的文章移植到小程序中

具体展示内容以及列表样式,我参考了订阅号助手中的「历史图文素材」,如下

所以在小程序中需要实现以下功能:

  1. 获取已发布的素材;
  2. 将数据渲染到前端,每条数据包含标题、概要、图片(这些字段接口都有返回);
  3. 调整列表样式;
  4. 点击文章跳转至详情;

 

1、获取已发布的素材

在之前一篇文章中介绍了如果通过接口获取公众号素材,传送门:开发一个微信小程序(1):获取文章列表

打开根目录下app.json,先创建2个文件夹 wx_articlewx_article_detail

最开始我的想法是通过接口来实时拿到微信公众号的文章,但是经过一番操作发现行不通,原因是:微信不允许直接在小程序中调用微信公众号的接口(主要是会暴露一些敏感信息,例如AppID)

 

然后我把调用公众号接口相关的功能写到了服务端(用flask即可),本地部署好服务后,尝试在小程序中调用自己定义的接口,结果发现小程序不允许直接调用ip地址,需要配置域名

 

接着我修改本地host文件,把ip和域名做了一个映射,使用postman通过域名调用flask接口时,提示成功,然后尝试在小程序调用,发现依然不行,这次提示我的域名不安全,不是https

 

接着我又去阿里云购买了一个域名,同时申请了一个免费的ssl证书,把域名和我本地ip绑定,同时修改flask启动方式,这样就能用https访问接口了,经过postman试验调用成功,然后尝试在小程序调用,发现又失败了,这次提示我的域名没有进行备案?

 

心态快炸了,没想到卡在了这里,微信小程序的限制也太多了

 

最后我决定先跳过这里,把公众号文章的数据提取到一个js文件中,然后在小程序中,直接去读这个js文件来获取数据,这样我就不必卡在这里,可以继续进行后面的学习了~

 

1.1 创建一个js文件,存放文章数据

在根目录下创建一个文件夹 data,然后在data下创建一个文件wx_article_data.js

里面的数据,是我通过接口拿到的,都粘贴到了这个文件中

1.2 读取并处理数据

打开 /pages/wx_article/wx_article.js,编辑如下代码

// pages/wx_article/wx_article.js

//引入本地数据
var wxArticleData = require("../../data/wx_article_data.js")

Page({

  /**
   * 页面的初始数据
   */
  data: {
    page: 1,
    posts: [],
    isloading: false,  //定一个标识符,默认为false,表示当前没有发送请求
  },

  //提取本地存储的微信公众号数据
  get_wx_article() {

      //开始取数据时,将isloading置为true
      this.setData({
        isloading: true  //为true时,表示正在发起请求
      })

      //展示loading效果
      wx.showLoading({
        title: '努力加载中...',
      })
    if (this.data.page === 1) {
      this.setData({
        posts: [...this.data.posts, ...wxArticleData.wxData.slice(0, 10)]  //第一次取前10个
      })
    }
    else {
      this.setData({
        //后续当page>1时,从下标开始取10个
        posts: [...this.data.posts, ...wxArticleData.wxData.slice(this.data.page*10-10, this.data.page*10)]
      })
    }
    
    //取完数后
    wx.hideLoading()  //隐藏loading效果
    //取数后,将isloading置为false
    this.setData({
      isloading: false  
    })
    
  },

  //通过编程式导航跳转到非tabBar页面
  gotodetail(e) {
    // console.log(e);
    const item = e.currentTarget.dataset['item'];
    // console.log(item);
    const article_url = item.url;
    const jpg_url = item.jpg_url;
    wx.navigateTo({
      url: '/pages/wx_article_detail/wx_article_detail?article_url='+
      encodeURIComponent(article_url)+'&jpg_url='+encodeURIComponent(jpg_url)
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.get_wx_article()
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    wx.setNavigationBarTitle({
      title: '公众号文章',  //把这个页面的标题自定义设置一下
    })
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {
    //请求前,需要重置参数
    this.setData({
      page: 1,
      posts: [],
    })
    this.get_wx_article()  //下拉刷新调用这个函数,重新发起请求
    wx.stopPullDownRefresh()  //真机上,刷新完后,调用这个方法,关闭下拉刷新
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    if(this.data.isloading) return  //如果isloading为true,则退出onReachBottom这个方法
    this.setData({
      page: this.data.page + 1  //上拉触底时,给页码加1,这样再发起请求时,就请求到了下一组的数据
    })
    this.get_wx_article()  //调用获取随笔的方法
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

主要是 get_wx_article() 方法,它的作用是读取 wx_article_data.js 中的数据并进行处理

每次提取10个,上拉页面触底时,加载下一组数据

 

data中定义了一个参数page,如果page=1,则取前10个数据

if (this.data.page === 1) {
      this.setData({
        posts: [...this.data.posts, ...wxArticleData.wxData.slice(0, 10)]  //第一次取前10个
      })
    }

如果page>1, 则从下标开始往后取10个

 else {
      this.setData({
        //后续当page>1时,从下标开始取10个
        posts: [...this.data.posts, ...wxArticleData.wxData.slice(this.data.page*10-10, this.data.page*10)]
      })
    }

在上拉触底事件中,给page+1

/**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    if(this.data.isloading) return  //如果isloading为true,则退出onReachBottom这个方法
    this.setData({
      page: this.data.page + 1  //上拉触底时,给页码加1,这样再发起请求时,就请求到了下一组的数据
    })
    this.get_wx_article()  //调用提取本地存储的微信公众号数据的方法
  },

2、将数据渲染到前端 & 调整列表样式

打开 /pages/wx_article/wx_article.wxml

<!--pages/wx_article/wx_article.wxml-->
<!-- <text>pages/wx_article/wx_article.wxml</text> -->

<!-- 文章列表 -->
<view class="box">
    <view class="items" wx:for="{{posts}}" wx:key="media_id" bindtap="gotodetail" data-item="{{item}}">
          <view class="father">
            <view class="son1">
              <text class="title">{{item.title}}</text>
              <text class="digest">{{item.digest}}</text>
            </view>
            <view class="son2">
              <image src="{{item.jpg_url}}" mode="aspectFill"></image>
            </view>
          </view>
          <!-- <view class="bottom-element">
              <text class="little-text">阅读:({{item.ViewCount}}) 评论:({{item.CommentCount}})</text>
              <text class="post-date">{{tools.splitDate(item.PostDate)}}</text>
          </view> -->
    </view>
</view>

 用for循环渲染数据,同时添加编程式导航,使得点击文章能够跳转至详情,使用bindtap绑定事件gotodetail

同时传递一个参数itemitem的值就是for循环的item对象,写法data-item="{{item}}"

 

gotodetail()方法如下

  //通过编程式导航跳转到非tabBar页面
  gotodetail(e) {
    // console.log(e);
    const item = e.currentTarget.dataset['item']; //接收页面传来的参数item
    // console.log(item);
    const article_url = item.url;  //获取item中的url
    const jpg_url = item.jpg_url; // 获取item中的jpg_url
    wx.navigateTo({
      url: '/pages/wx_article_detail/wx_article_detail?article_url='+
      encodeURIComponent(article_url)+'&jpg_url='+encodeURIComponent(jpg_url)
      //这里对文章url和图片url做了转码处理,因为url中包含很多特殊字符,直接传递会丢失
    })
  },

 

接下来再调整样式

主要是把标题放上面,概要放下面,图片放右侧

打开/pages/wx_article/wx_article.wxss

/* pages/wx_article/wx_article.wxss */

.items {
  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);  /*设置每张小卡片的颜色*/
}

.father{
  display: flex;
}
.son1{
  width: 80%;
  display: flex;
  flex-direction: column;  /*使元素纵向布局(默认为横向)*/
}
.son2{
  width: 20%;
  display: flex;
}
image{
  height: 90%;
  width: 100%;
  margin-right: 20rpx;
  margin-left: 10rpx;
}

.title{
  font-size:32rpx;
  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; /* 从上到下垂直排列子元素*/
}

.digest {
  font-size: 27rpx;
  color: gray;
  margin-top: 30rpx;
  margin-left: 20rpx;
  display: -webkit-box;  /*设置为弹性盒子*/
  overflow:hidden; /*超出隐藏*/
  text-overflow: ellipsis; /*显示省略号*/
  -webkit-line-clamp: 1; /*多少行后显示省略号,这里设置为第一行超出后显示省略号*/
  word-break:break-all; /*强制英文单词自动换行,可要可不要*/
  -webkit-box-orient: vertical; /* 从上到下垂直排列子元素*/
}

 

3、文章详情

如果我们拿到公众号文章的url后,可以使用<web-view>标签来展示详情

前提是要把公众号与小程序进行关联,打开微信公众平台,找到如下位置进行关联即可

 

对应代码如下

/pages/wx_article_detail/wx_article_detail.js

// pages/wx_article_detail/wx_article_detail.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    query: {} ,// 接收navigator传来的参数
    article_url: "",
    jpg_url: ""
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.setData({
      query: options,  //把navigator传来的参数赋给query
      article_url: decodeURIComponent(options.article_url),
      jpg_url: decodeURIComponent(options.jpg_url)
    })
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    wx.setNavigationBarTitle({
      title: '文章详情',  //把这个页面的标题自定义设置一下
    })
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

 pages/wx_article_detail/wx_article_detail.wxml 

<!--pages/wx_article_detail/wx_article_detail.wxml-->
<web-view src="{{article_url}}"></web-view>
<!-- <text>{{article_url}}</text> -->

OK,这样就完成了公众号文章列表功能页面

 

 

 

 

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