组件化框架 WePY 开发入门(二) —— 博客首页文章列表重构
上篇教程,学院君已经给大家初步介绍了基于小程序组件化框架 WePY 的项目初始化和目录结构,今天开始我们将花几篇教程的篇幅通过 WePY 框架来重构之前通过原生框架开发的博客应用小程序版,并且在此基础上实现用户授权登录及点赞功能,最后将这个小程序上线,从而演示完整的小程序开发生命周期。
重构的时候,后端接口不用做任何调整,只需要开发小程序页面即可。
我们在 PHPStorm 中打开上篇教程创建的全新小程序项目 blog-lite
,在 WePY 框架中开发小程序页面非常简单,就和在 Vue 中编写单文件组件一样,打开首页页面文件 src/pages/index.wpy
,先清空页面代码。
编写列表项组件
和原生框架一样,我们为首页文章列表项编写独立组件,在 src/components
目录下新建一个 card.wpy
,并编写组件代码如下(其实就是把原来原生框架实现代码合并过来):
<style lang="less">
@font-face {
font-family: "iconfont";
src: url('iconfont.eot?t=1545317804991');
/* IE9*/
src: url('iconfont.eot?t=1545317804991#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), url('iconfont.ttf?t=1545317804991') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('iconfont.svg?t=1545317804991#iconfont') format('svg');
/* iOS 4.1- */
font-weight: normal;
font-style: normal;
}
.card {
-webkit-font-smoothing: antialiased;
background-color: #fff;
padding: 25rpx 25rpx;
margin-bottom: 30rpx;
overflow: hidden;
color: #333;
.title {
font-size: 18px;
-webkit-line-clamp: 2;
line-height: 1.2;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.content-area {
display: -webkit-box;
.left-area {
-webkit-box-orient: vertical;
-webkit-box-flex: 1;
.card-content {
line-height: 1.3;
font-size: 14px;
margin: 10rpx 0;
font-family: HelveticaNeue-Light;
overflow: hidden;
color: #666;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.info-area {
font-size: 10pt;
color: #666;
opacity: .8;
font-family: 'iconfont';
.posted-date {
&:before {
content: '\e64e';
margin-right: 10rpx;
}
}
.views {
margin-left: 30rpx;
&:before {
content: '\e666';
margin-right: 10rpx;
}
}
}
}
.right-area {
margin-left: 20rpx;
}
.thumbnail {
width: 150rpx;
height: 150rpx;
background-color: #eee;
margin-top: 26rpx;
}
}
}
</style>
<template>
<view class="card">
<text class="title">{{title}}</text>
<view class="content-area">
<view class="left-area">
<text class="card-content">{{content}}</text>
<view class="info-area">
<text class="posted-date">{{date}}</text>
<text class="views">{{views}}</text>
</view>
</view>
<view class="right-area">
<image src='{{thumbnail}}' class="thumbnail" mode="aspectFill"/>
</view>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class Card extends wepy.component {
props = {
title: String,
content: String,
category: String,
date: String,
views: Number,
thumbnail: String
}
}
</script>
单独来看,和原生框架中的代码几乎一样,不同之处主要有两个:
- 将之前 WXML、WXSS、JS 分别存放在不同文件不同,WePY 框架通过统一的单文件来定义组件代码,而且页面结构和 Vue 单文件组件一模一样;
- 在原生框架中通过 WXSS 定义样式代码,这里通过 Less 语法来定义样式代码,此外还支持 Sass 语法,这一点和 Vue 单文件组件也一样。
如果你看过原来原生框架的实现,同时对 Vue 有比较熟悉,理解上述组件代码应无大碍。下面我们来定义首页页面,并在页面中引入刚刚定义的组件。
编写博客首页
首页的页面结构和组件一样,也是分为样式、模板和脚本三部分。
编写样式代码
打开 src/pages/index.wpy
,编写样式代码如下:
<style lang="scss">
.container {
background-color: #eee;
}
.title_en {
position: absolute;
bottom: 0;
color: #fff;
z-index: 2;
padding: 20px;
}
.cards-area {
margin-top: 30rpx;
width: 100%;
.date{
color: #666;
text-align: center;
margin-bottom: 10rpx;
opacity: .8;
&:before{
position: absolute;
content: "————";
left:450rpx;
right:0;
}
&:after{
position: absolute;
content: "————";
left:0;
right:450rpx;
}
}
}
.info{
color:gray;
opacity:.8;
margin-bottom: 20rpx;
&.loading{
width: 70rpx;
height: 70rpx;
}
}
</style>
这里我们标注样式标签属性 lang
为 scss
,表示这里通过 Sass 语法定义页面样式,具体的样式代码和之前原生框架一样。
编写模板代码
接下来,我们在 index.wpy
中编写博客首页模板代码,和 Vue 组件一样,通过 template
标签来定义模板代码:
<template>
<view class="container">
<view class="cards-area">
<repeat for="{{articles}}">
<view @tap="tap('{{item.id}}')" wx:if="{{item.id}}">
<card :title="item.title" :content="item.summary" :category="item.category" :date="item.posted_at" :views="item.views" :thumbnail="item.thumb"/>
</view>
</repeat>
</view>
<text class="info" wx:if="{{info}}">{{info}}</text>
<image wx:else class="info loading" src="../resources/assets/loading.gif"/>
</view>
</template>
基本代码和原生框架也是一样,这里我们引入了 card
组件,用于渲染文章列表项,此外在 WePY 框架中,我们通过 repeat 实现组件循环渲染。
编写业务逻辑代码
页面主要逻辑通过 JS 代码来定义,我们在页面 JS 脚本中引入 card
组件,定义页面渲染用到的变量,以及通过 API 获取文章列表数据并将其同步到变量中,此外还定义了上划翻页和首页分享方法,在 index.wpy
最后追加 JS 代码如下:
<script>
import wepy from 'wepy'
import Card from '../components/card'
export default class Index extends wepy.page {
config = {
navigationBarTitleText: 'Laravel学院',
window: {
enablePullDownRefresh: true
}
}
components = {
card: Card
}
data = {
articles: [],
isLoadingMore: false,
currentPage: 1,
info: ''
}
methods = {
tap(id) {
wx.navigateTo({
url: `/pages/post?id=${id}` // 打开一个新的同路由页面,但指定不同的数据初始值
})
}
}
onLoad() {
wx.showLoading({
title: '加载中'
})
this.loadList()
}
onPullDownRefresh() {
wx.stopPullDownRefresh()
}
onReachBottom() {
this.currentPage++
if (this.currentPage >= 20) { // 最多只能加载20页
this.isLoadingMore = false
this.info = '没有更多文章了'
this.$apply()
return
}
this.isLoadingMore = true
this.loadList()
}
onShareAppMessage() {
return {
title: 'Laravel学院',
path: '/pages/index'
}
}
loadList() {
wx.request({
url: `https://blog.laravelacademy.org/api/v1/articles?page=${this.currentPage}`,
success: (res) => {
if (res.data.message === 'success') {
this.articles = this.articles.concat(res.data.articles)
} else {
this.info = '加载文章列表失败,请重试'
}
this.$apply()
wx.hideLoading()
}
})
}
}
</script>
具体的业务逻辑功能和原生框架中差不多,只是在 WePY 框架具体实现细节略微有些出入。
重新编译小程序
编写好上述页面代码后,就可以重新编译小程序了,在此之前,先安装以下 NPM 依赖以便可以正常编译 Sass:
npm install node-sass
npm install wepy-compiler-sass
然后我们开启前端资源自动编译:
wepy build --watch
打开微信开发者工具,进入 blog-lite
小程序项目,即可在页面左侧预览区域看到基于 WePY 框架重构的博客首页了:
和原生框架渲染效果和功能特性一模一样。
下一篇我们将继续基于 WePY 框架重构博客详情页。
2 Comments
loading.gif 这张图片没有
文中用到了一张
loading.gif
图片但在项目文件夹里并没有这张图片。找一张
loading.gif
图片放入/src/resources/assets/
目录即可。