原生框架开发入门(五) —— 博客文章详情页实现(下)


上一篇教程中,我们通过测试数据渲染了小程序的文章详情页,这一篇教程我们将通过访问后端 API 接口来获取文章数据,以便实现文章详情页数据渲染。

提供后端 API 接口

定义路由

首先,我们需要在博客项目 blog57routes/api.php 中新增一个 API 路由:

Route::middleware('throttle:60,1')->prefix('v1')->group(function() {
    // 文章首页
    Route::get('/articles', 'API\PostController@index');
    // 文章详情页
    Route::get('/article/{id}', 'API\PostController@detail')->where(['id' => '[1-9]{1}[0-9]*']);
});

我们通过 /api/v1/article/{id} 获取文章详情数据,并且正则约束 id 参数是大于 1 的整型数据。

编写控制器方法

我们将通过 API 资源类来处理返回文章数据格式以满足前端需要,为此需要创建对应的 API 资源类 PostResource

php artisan make:resource PostResource

该命令会在 app/Http/Resources 目录下创建一个 PostResource.php 文件,我们编写该文件代码如下:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'image' => url(config('blog.uploads.webpath') . '/' . $this->page_image),
            'content' => $this->content_html,
            'author' => '学院君',
            'posted_at' => $this->publish_date,
            'views' => mt_rand(1, 100000),
            'votes' => mt_rand(1, 1000)
        ];
    }
}

由于文章表 posts 没有用户相关字段和浏览数、点赞数字段,我们这里暂时返回写死的或者随机数据。接下来,我们在控制器 API/PostController 中定义 detail 方法:

public function detail($id)
{
    $post = Post::findOrFail($id);
    return new PostResource($post);
}

非常简单,如果文章不存在,返回 404 响应,否则通过资源类 PostResource 进行转化后返回给调用方。

测试 API 接口访问

这样,我们就可以通过 http://blog57.test/api/v1/article/1 访问指定博客文章数据了:

修改传入的文章 ID 即可获取的对应的文章数据。

测试完成后将修改代码提交、上线,以便在线上可以通过小程序配置的域名 https://blog.laravelacademy.org 访问:

引入 wxParse 实现富文本渲染

我们在上篇教程中是通过小程序自带的 rich-text 组件对富文本进行渲染,如果是从后台 API 接口获取的数据,还需要对文章正文富文本字符串进行处理,方能在小程序中显示,如果要应用一些事件和复杂样式,会很麻烦,所以,这里引入一个第三方富文本渲染组件 —— wxParse,该组件同时支持 HTML 和 Markdown 渲染,而且,它会自动将 HTML 字符串进行转化,并加上样式,然后通过 wxParse 组件进行渲染。

在使用该组件之前,首选需要将其下载到本地:

git clone https://github.com/icindy/wxParse.git

然后将该项目中的 wxParse/wxParse 子目录拷贝到小程序项目的 pages/components 组件目录下:

这样,我们就可以在小程序文章详情页面通过该组件进行富文本渲染了。

通过 API 请求获取文章数据

正如开篇所说,在上篇教程中学院君是通过填充测试数据渲染文章列表的,现在,我们将其修改为通过后台 API 获取文章数据。

回到微信小程序项目,打开 pages/detail/detail.js 文件,删除测试文章数据:

/**
 * 页面的初始数据
 */
data: {
    article: {},
    info: ''
},

然后我们在 Page 对象中新增一个 loadArticle 方法用于从后端 API 接口获取文章数据并设置到 data 中的 article 属性上:

/**
 * 通过后端接口获取文章数据
 */
loadArticle: function () {
    var that = this
    wx.showLoading({
        title: '加载中'
    })
    wx.request({
        url: `https://blog.laravelacademy.org/api/v1/article/${that.data.article.id}`,
        success: (res) => {
          that.setData({
              article: {
                title: res.data.data.title,
                image: res.data.data.image,
                author: res.data.data.author,
                content: res.data.data.content,
                posted_at: res.data.data.posted_at,
                views: res.data.data.views,
                votes: res.data.data.votes
              }
          })
          // 引入 wxParse 组件处理文章正文
          var wxParse = require('../components/wxParse/wxParse.js')
          wxParse.wxParse('article_content', 'html', that.data.article.content, that, 1)
        },
        fail: function () {
          that.data.info = '获取文章详情数据失败'
        },
        complete: function () {
          wx.hideLoading()
        }
    })
}

这里我们仍然通过 wx.request 发起异步请求,从博客后端 API 接口获取文章详情数据,如果获取成功,则通过返回文章数据并设置 data.article 属性,否则通过 data.info 属性提示用户加载失败。

接下来,我们要在 onLoad 里调用这个方法,以便页面加载完成后就能看到文章列表数据:

onLoad: function (options = {}) {
    this.data.article.id = options.id
    this.loadArticle()
},

我们通过 options 从路由中获取文章 ID 参数,并将其设置到 data.article.id,以便在 loadArticle 方法中通过该值去后台获取指定文章数据。

文章详情页渲染

接下来,打开 pages/detail/detail.wxml,在视图层引入 wxParse 组件来渲染文章正文:

<view class="content">
    <image lazy-load='true' style='max-width:100%;max-height:200px;' src='{{article.image}}'></image>
    <import src="../components/wxParse/wxParse.wxml"/>
    <template is="wxParse" data="{{wxParseData:article_content.nodes}}"/>
</view>

注意到我们还在正文最上方通过小程序内置的 image 组件来渲染文章题图。

wxParse 组件会为所有的富文本 HTML 标签创建对应的 class 类名,比如 <p> 标签的 class 属性会包含 wxParse-p 类名,image 标签的 class 属性会包含 wxParse-image 类名,等等,并且为这些类定义了相应的默认样式,我们可以在 pages/detail/detail.wxss 中引入 wxParse 定义的这些默认样式:

@import "../components/wxParse/wxParse.wxss";

当然,你也可以对默认样式进行自定义:

.content .wxParse-p {
  margin: 0 0 15rpx; 
  outline: 0;
  padding: 0;
  vertical-align: baseline;
}

这样,重新编译后,就可以在微信开发者工具左侧预览界面从首页文章列表点击任意一篇文章,进入详情页看到通过 API 接口获取文章数据渲染的页面了:

分享小程序详情页

最后,我们在详情页通过编写页面事件处理函数 onShareAppMessage 实现小程序分享功能,打开 pages/detail/detail.js,修改 onShareAppMessage 函数代码如下:

/**
 * 用户点击右上角分享
 */
onShareAppMessage: function () {
    let id = this.data.article.id
    let title = this.data.article.title
    return {
      title: `Laravel学院 - ${title}`,
      path: `/pages/detail/detail?id=${id}`
    }
},

这样我们点击小程序详情页右上角的「...」,点击转发按钮,即可分享这篇文章给为微信好友了:

好了,通过原生框架开发微信小程序我们就简单聊到这里,从下一篇开始,我们将给大家介绍如何通过小程序官方组件化开发框架 WePY 更高效地开发微信小程序。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 原生框架开发入门(四) —— 博客文章详情页实现(上)

>> 下一篇: 组件化框架 WePY 开发入门(一) —— 项目初始化和目录结构