深秋暖阳 發表於 2022-6-9 16:44:00

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

<p><span style="font-size: 13px">本篇讲一下如何把微信公众号中发布的文章移植到小程序中</span></p>
<p><span style="font-size: 13px">具体展示内容以及列表样式,我参考了订阅号助手中的「历史图文素材」,如下</span></p>
<p><img src="https://img2022.cnblogs.com/blog/1158674/202206/1158674-20220609152211659-705542517.png" width="227" height="491"></p>
<p><span style="font-size: 13px">所以在小程序中需要实现以下功能:</span></p>
<ol class="ol-level-0">
<li><span style="font-size: 13px">获取已发布的素材;</span></li>
<li><span style="font-size: 13px">将数据渲染到前端,每条数据包含标题、概要、图片(这些字段接口都有返回);</span></li>
<li><span style="font-size: 13px">调整列表样式;</span></li>
<li><span style="font-size: 13px">点击文章跳转至详情;</span></li>
</ol>
<p>&nbsp;</p>
<h3 id="1%E3%80%81%E8%8E%B7%E5%8F%96%E5%B7%B2%E5%8F%91%E5%B8%83%E7%9A%84%E7%B4%A0%E6%9D%90"><span style="font-size: 15px">1、获取已发布的素材</span></h3>
<p><span style="font-size: 13px">在之前一篇文章中介绍了如果通过接口获取公众号素材,传送门:开发一个微信小程序(1):获取文章列表</span></p>
<p><span style="font-size: 13px">打开根目录下<code>app.json</code>,先创建2个文件夹 <code>wx_article</code>和 <code>wx_article_detail</code></span></p>
<p><img src="https://img2022.cnblogs.com/blog/1158674/202206/1158674-20220609152448506-1782855053.png" width="550" height="328"></p>
<p><span style="font-size: 13px">最开始我的想法是通过接口来实时拿到微信公众号的文章,但是经过一番操作发现行不通,原因是:微信不允许直接在小程序中调用微信公众号的接口(主要是会暴露一些敏感信息,例如AppID)</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">然后我把调用公众号接口相关的功能写到了服务端(用flask即可),本地部署好服务后,尝试在小程序中调用自己定义的接口,结果发现小程序不允许直接调用ip地址,需要配置域名</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">接着我修改本地host文件,把ip和域名做了一个映射,使用postman通过域名调用flask接口时,提示成功,然后尝试在小程序调用,发现依然不行,这次提示我的域名不安全,不是https</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">接着我又去阿里云购买了一个域名,同时申请了一个免费的ssl证书,把域名和我本地ip绑定,同时修改flask启动方式,这样就能用https访问接口了,经过postman试验调用成功,然后尝试在小程序调用,发现又失败了,这次提示我的域名没有进行备案?</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">心态快炸了,没想到卡在了这里,微信小程序的限制也太多了</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">最后我决定先跳过这里,把公众号文章的数据提取到一个js文件中,然后在小程序中,直接去读这个js文件来获取数据,这样我就不必卡在这里,可以继续进行后面的学习了~</span></p>
<p>&nbsp;</p>
<p id="1.1-%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAjs%E6%96%87%E4%BB%B6%EF%BC%8C%E5%AD%98%E6%94%BE%E6%96%87%E7%AB%A0%E6%95%B0%E6%8D%AE"><strong><span style="font-size: 15px">1.1 创建一个js文件,存放文章数据</span></strong></p>
<p><span style="font-size: 13px">在根目录下创建一个文件夹 <code>data</code>,然后在<code>data</code>下创建一个文件<code>wx_article_data.js</code></span></p>
<p><span style="font-size: 13px">里面的数据,是我通过接口拿到的,都粘贴到了这个文件中</span></p>
<p><img src="https://img2022.cnblogs.com/blog/1158674/202206/1158674-20220609152553359-306672134.png" width="627" height="328"></p>
<p id="1.2-%E8%AF%BB%E5%8F%96%E5%B9%B6%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE"><span style="font-size: 15px"><strong>1.2 读取并处理数据</strong></span></p>
<p><span style="font-size: 13px">打开 <code>/pages/wx_article/wx_article.js</code>,编辑如下代码</span></p>
<pre class="language-javascript highlighter-hljs"><code>// 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&gt;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)+'&amp;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() {

}
})</code></pre>
<p><span style="font-size: 13px">主要是 <code>get_wx_article() </code>方法,它的作用是读取<code> wx_article_data.js </code>中的数据并进行处理</span></p>
<p><span style="font-size: 13px">每次提取10个,上拉页面触底时,加载下一组数据</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px">在<code>data</code>中定义了一个参数<code>page</code>,如果<code>page=1</code>,则取前10个数据</span></p>
<pre class="language-javascript highlighter-hljs"><code>if (this.data.page === 1) {
      this.setData({
      posts: [...this.data.posts, ...wxArticleData.wxData.slice(0, 10)]//第一次取前10个
      })
    }</code></pre>
<p><span style="font-size: 13px">如果<code>page&gt;1</code>, 则从下标开始往后取10个</span></p>
<pre class="language-javascript highlighter-hljs"><code> else {
      this.setData({
      //后续当page&gt;1时,从下标开始取10个
      posts: [...this.data.posts, ...wxArticleData.wxData.slice(this.data.page*10-10, this.data.page*10)]
      })
    }</code></pre>
<p><span style="font-size: 13px">在上拉触底事件中,给page<code>+1</code></span></p>
<pre class="language-javascript highlighter-hljs"><code>/**
   * 页面上拉触底事件的处理函数
   */
onReachBottom() {
    if(this.data.isloading) return//如果isloading为true,则退出onReachBottom这个方法
    this.setData({
      page: this.data.page + 1//上拉触底时,给页码加1,这样再发起请求时,就请求到了下一组的数据
    })
    this.get_wx_article()//调用提取本地存储的微信公众号数据的方法
},</code></pre>
<h3 id="2%E3%80%81%E5%B0%86%E6%95%B0%E6%8D%AE%E6%B8%B2%E6%9F%93%E5%88%B0%E5%89%8D%E7%AB%AF-&amp;-%E8%B0%83%E6%95%B4%E5%88%97%E8%A1%A8%E6%A0%B7%E5%BC%8F"><span style="font-size: 15px">2、将数据渲染到前端 &amp; 调整列表样式</span></h3>
<p><span style="font-size: 13px">打开 <code>/pages/wx_article/wx_article.wxml</code></span></p>
<pre class="language-html highlighter-hljs"><code>&lt;!--pages/wx_article/wx_article.wxml--&gt;
&lt;!-- &lt;text&gt;pages/wx_article/wx_article.wxml&lt;/text&gt; --&gt;

&lt;!-- 文章列表 --&gt;
&lt;view class="box"&gt;
    &lt;view class="items" wx:for="{{posts}}" wx:key="media_id" bindtap="gotodetail" data-item="{{item}}"&gt;
          &lt;view class="father"&gt;
            &lt;view class="son1"&gt;
            &lt;text class="title"&gt;{{item.title}}&lt;/text&gt;
            &lt;text class="digest"&gt;{{item.digest}}&lt;/text&gt;
            &lt;/view&gt;
            &lt;view class="son2"&gt;
            &lt;image src="{{item.jpg_url}}" mode="aspectFill"&gt;&lt;/image&gt;
            &lt;/view&gt;
          &lt;/view&gt;
          &lt;!-- &lt;view class="bottom-element"&gt;
            &lt;text class="little-text"&gt;阅读:({{item.ViewCount}}) 评论:({{item.CommentCount}})&lt;/text&gt;
            &lt;text class="post-date"&gt;{{tools.splitDate(item.PostDate)}}&lt;/text&gt;
          &lt;/view&gt; --&gt;
    &lt;/view&gt;
&lt;/view&gt;</code></pre>
<p><span style="font-size: 13px">&nbsp;用for循环渲染数据,同时添加编程式导航,使得点击文章能够跳转至详情,使用<code>bindtap</code>绑定事件<code>gotodetail</code></span></p>
<p><span style="font-size: 13px">同时传递一个参数<code>item</code>,<code>item</code>的值就是for循环的<code>item对象</code>,写法<code>data-item="{{item}}"</code></span></p>
<p>&nbsp;</p>
<p><span style="font-size: 13px"><code>gotodetail()</code>方法如下</span></p>
<div class="developer-code-block">
<pre class="language-javascript highlighter-hljs"><code>//通过编程式导航跳转到非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)+'&amp;jpg_url='+encodeURIComponent(jpg_url)
      //这里对文章url和图片url做了转码处理,因为url中包含很多特殊字符,直接传递会丢失
    })
},</code></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 13px">接下来再调整样式</span></p>
<p><span style="font-size: 13px">主要是把标题放上面,概要放下面,图片放右侧</span></p>
<p><span style="font-size: 13px">打开<code>/pages/wx_article/wx_article.wxss</code></span></p>
<pre class="language-css highlighter-hljs"><code>/* 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; /* 从上到下垂直排列子元素*/
}</code></pre>
<p>&nbsp;</p>
<h3 id="3%E3%80%81%E6%96%87%E7%AB%A0%E8%AF%A6%E6%83%85"><span style="font-size: 15px">3、文章详情</span></h3>
<p><span style="font-size: 13px">如果我们拿到公众号文章的url后,可以使用<code>&lt;web-view&gt;</code>标签来展示详情</span></p>
<p><span style="font-size: 13px">前提是要把公众号与小程序进行关联,打开微信公众平台,找到如下位置进行关联即可</span></p>
<p><img src="https://img2022.cnblogs.com/blog/1158674/202206/1158674-20220609153329814-48245975.png" width="754" height="247">&nbsp;</p>
<p><span style="font-size: 13px">对应代码如下</span></p>
<p><span style="font-size: 13px"><code>/pages/wx_article_detail/wx_article_detail.js</code></span></p>
<pre class="language-javascript highlighter-hljs"><code>// 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() {

}
})</code></pre>
<p><code><span style="font-size: 13px">&nbsp;pages/wx_article_detail/wx_article_detail.wxml&nbsp;</span></code></p>
<pre class="language-html highlighter-hljs"><code>&lt;!--pages/wx_article_detail/wx_article_detail.wxml--&gt;
&lt;web-view src="{{article_url}}"&gt;&lt;/web-view&gt;
&lt;!-- &lt;text&gt;{{article_url}}&lt;/text&gt; --&gt;</code></pre>
<p><span style="font-size: 13px">OK,这样就完成了公众号文章列表功能页面</span></p>
<figure class="">
<div class="image-block">&nbsp;</div>
</figure>
<p><img src="https://img2022.cnblogs.com/blog/1158674/202206/1158674-20220609153556368-555575087.png" width="803" height="323">&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<figure class="">
<div class="image-block">&nbsp;</div>
</figure><br><br>
来源:https://www.cnblogs.com/hanmk/p/16359534.html
頁: [1]
查看完整版本: 开发一个微信小程序(3):编写公众号文章列表