1、集成Bmob小程序SDK作為數(shù)據(jù)存儲(chǔ)
2、wemark解析markdown文本
3、列表頁(yè)布局與上拉無(wú)限加載
實(shí)現(xiàn)的效果
進(jìn)入Bmob官網(wǎng):http://bmob.cn/,注冊(cè)一個(gè)賬號(hào),免費(fèi)的賬號(hào)可以創(chuàng)建8個(gè)子應(yīng)用,每個(gè)應(yīng)用單表列數(shù)是20列,如要購(gòu)買(mǎi)付費(fèi),可以分別買(mǎi)100元與1000元檔,詳見(jiàn)官網(wǎng)價(jià)目表。
1、創(chuàng)建一個(gè)應(yīng)用
2、查看它的key信息以及配置自己小程序的key信息,如果有支付的,加配支付MchID與key,支付對(duì)于付費(fèi)會(huì)員才可用。
3、進(jìn)入網(wǎng)址:http://docs.bmob.cn/data/wechatApp/a_faststart/doc/index.html,來(lái)查閱小程序文檔
4、為小程序添加白名單
在小程序管理后臺(tái),進(jìn)入設(shè)置->開(kāi)發(fā)設(shè)置->服務(wù)器域名,為4個(gè)域名統(tǒng)一添加地址為api.bmob.cn。
這事實(shí)是不對(duì)了,真正在填寫(xiě)的要等小程序報(bào)錯(cuò)時(shí)才知道,如下圖
于是刪除掉之前的填寫(xiě)的白名單api.bmob.cn,而使用小程序真正使用到的這個(gè)三級(jí)域名:4552ad36df85c1f29953ae3679c69248.bmobcloud.com
,小程序以前是1月允許3次修改白名單,目前是1個(gè)月允許5次,少走一些彎路可以節(jié)省一些次數(shù)的。
下圖是我更正后的配置信息
1、創(chuàng)建小程序項(xiàng)目,appid使用的就是剛剛配置在Bmob后臺(tái)的那個(gè)appid。
2、打開(kāi)app.js引入bmob的js sdk庫(kù),并初始化
var Bmob = require('utils/bmob.js');
Bmob.initialize("你的Application ID", "你的REST API Key");
sdk下載地址是:https://github.com/bmob/bmob-WeApp-sdk
由于沒(méi)有寫(xiě)專(zhuān)門(mén)的web后臺(tái),于是直接在bmob的后臺(tái)可視化界面錄入
1、建表與字段
| 字段名 | 類(lèi)型 | 注釋 |
|---|---|---|
| title | String | 標(biāo)題 |
| content | String | 內(nèi)容 |
| priority | Number | 越大越靠前 |
2、根目錄下新建article目錄,再新建list文件夾,下面放著list.wxml、list.wxss與list.js
注意要將剛剛創(chuàng)建的頁(yè)面文件添加到app.json中
{
"pages":[
"article/list/list"
]
}
3、引入bmob.js文件,讀取所有的文章列表列表
var Bmob = require('../../utils/bmob.js');
var that;
Page({
onLoad: function () {
that = this;
var Article = Bmob.Object.extend("article");
var query = new Bmob.Query(Article);
// 按照priority逆序排列
query.descending('priority');
// 查詢(xún)所有數(shù)據(jù)
query.find({
success: function(results) {
// 請(qǐng)求成功將數(shù)據(jù)存入article_list
that.setData({
article_list: results
});
},
error: function(error) {
alert("查詢(xún)失敗: " + error.code + " " + error.message);
}
});
}
});
定義一個(gè)全局的that變量,以解決異步請(qǐng)求時(shí)作用域改變的問(wèn)題,以后的每一個(gè)方法都使用that以代替this。
4、制作列表頁(yè)布局文件與樣式
<!-- 遍歷文章列表 -->
<view wx:for="{{article_list}}" class="row" wx:key="">
<!-- 縮略圖 -->
<view>
<image src="{{item.thumb}}" class="thumb" mode="aspectFill" />
</view>
<!-- 標(biāo)題與日期 -->
<view>
<!-- 標(biāo)題 -->
<view class="title">{{item.title}}</view>
<!-- 日期 -->
<view class="time">{{item.updatedAt}}</view>
</view>
</view>
其中圖片使用了aspectFill模式,保證了圖片不變形且是填充滿(mǎn)<image>標(biāo)簽的;且<image>需要包在<view>中,不然css設(shè)定的寬度無(wú)效,僅高度有效。
/*每行行內(nèi)元素按行分布*/
.row {
display: flex;
flex-direction: row;
margin: 10px;
}
/*縮略圖*/
.thumb {
width: 100px;
height: 75px;
margin-right: 10px;
margin-top: 5px;
}
/*文章標(biāo)題*/
.title {
color: #333;
margin: 10px 0;
line-height: 130%;
}
/*日期*/
.time {
font-size: 14px;
color: #999;
margin: 10px 0;
}
使用了flex布局作為左右排列與上下排列的控制。其中縮略圖與文本呈左右排列, 標(biāo)題與日期呈上面排列。
剛剛實(shí)現(xiàn)的列表是讀取的全部,一般來(lái)講會(huì)有上拉加載的效果,也就是分頁(yè)
1、通過(guò)skip與limit實(shí)現(xiàn)分頁(yè)
將請(qǐng)求代碼獨(dú)立出一個(gè)成員方法loadArticle(),以方便下拉加載與onLoad加載是共用
loadArticle: function () {
var page_size = 10;
...
// 分頁(yè)
query.limit(page_size);
query.skip(that.data.page_index * page_size);
// 查詢(xún)所有數(shù)據(jù)
query.find({
success: function(results) {
// 請(qǐng)求成功將數(shù)據(jù)存入article_list
that.setData({
article_list: that.data.article_list.concat(results)
});
});
}
使用concat方法將分頁(yè)請(qǐng)求得到數(shù)組合并入原始數(shù)組,以求不斷迭加。
onReachBottom: function () {
that.setData({
page_index: ++that.data.page_index
});
that.loadArticle();
}
實(shí)現(xiàn)onReachBottom方法加page_index不斷加1,使頁(yè)碼遞增后,再請(qǐng)求Bmob數(shù)據(jù)。
2、底部加上加載狀態(tài)的文本顯示
頁(yè)面上加一個(gè)<view>
<view class="loading-indicator">
{{loadingTip}}
</view>
配上樣式
/*上拉加載提示*/
.loading-indicator {
text-align: center;
font-size: 12px;
margin: 10px 0;
}
js文件如下處理
data: {
loadingTip: '上拉加載更多'
}
聲明好loadingTip數(shù)據(jù)后,如果本次請(qǐng)求返回的行數(shù)小于每頁(yè)行數(shù)代表是否還有更多數(shù)據(jù)(粗略的算法,更合理地做法是多請(qǐng)求一行例如11行,返回不夠數(shù)了才是真沒(méi)有下一頁(yè)了)
// 判斷上拉加載狀態(tài)
if (results.length < page_size) {
that.setData({
loadingTip: '沒(méi)有更多內(nèi)容'
});
}
1、處理帶參跳轉(zhuǎn)
首先,為.row行添加一個(gè)點(diǎn)擊事件
<view wx:for="{{article_list}}" class="row" wx:key="" bindtap="showDetail" data-index="{{index}}">
然后,取出wxml綁定的數(shù)值,設(shè)置跳轉(zhuǎn)路徑
showDetail: function (e) {
// 獲取wxml元素綁定的index值
var index = e.currentTarget.dataset.index;
// 取出objectId
var objectId = that.data.article_list[index].id;
// 跳轉(zhuǎn)到詳情頁(yè)
wx.navigateTo({
url: '../detail/detail?objectId=' + objectId
});
}
最后,在article目錄創(chuàng)建detail文件夾,除創(chuàng)建同上頁(yè)面3個(gè)文件外,再創(chuàng)建一個(gè).json文件,配置頁(yè)面標(biāo)題欄文本顯示
{
"navigationBarTitleText": "文章詳情"
}
2、detail頁(yè)面接收參數(shù)
Page({
onLoad: function (options) {
// 獲取傳參
var objectId = options.objectId;
}
})
3、取出文章數(shù)據(jù)
以objectId為參數(shù),向Bmob請(qǐng)求文詳情數(shù)據(jù)
var Bmob = require('../../utils/bmob.js');
var that;
Page({
data: {
content: ''
},
onLoad: function (options) {
that = this;
// 獲取傳參
var objectId = options.objectId;
// 向Bmob請(qǐng)求詳情頁(yè)數(shù)據(jù)
var Article = Bmob.Object.extend("article");
//創(chuàng)建查詢(xún)對(duì)象,入口參數(shù)是對(duì)象類(lèi)的實(shí)例
var query = new Bmob.Query(Article);
//查詢(xún)單條數(shù)據(jù),第一個(gè)參數(shù)是這條數(shù)據(jù)的objectId值
query.get(objectId, {
success: function(result) {
// 查詢(xún)成功,調(diào)用get方法獲取對(duì)應(yīng)屬性的值
var content = result.get("content");
that.setData({
content: content
});
},
error: function(object, error) {
// 查詢(xún)失敗
}
});
}
})
4、渲染頁(yè)面
<view class="container">
<view class="title">{{article.title}}</view>
<view class="time">{{article.updatedAt}}</view>
<view class="content">{{article.content}}</view>
</view>
外層包裹一個(gè)container是為了設(shè)置邊距,美化頁(yè)面。
/*外部容器*/
.container {
margin: 20px 10px;
}
/*標(biāo)題*/
.title {
text-align: center;
color: #333;
font-size: 20px;
margin: 10px 0;
}
/*日期*/
.time {
text-align: center;
color: #999;
font-size: 12px;
margin: 10px 0;
}
/*內(nèi)容*/
.content {
margin: 20px 0;
font-size: 14px;
color: #555;
line-height: 140%;
}
如此,已經(jīng)順利獲取到了詳情頁(yè)內(nèi)容并顯示出來(lái)了。剩下就是將markdown轉(zhuǎn)為正常的顯示。
有大牛寫(xiě)好了一個(gè)針對(duì)小程序的markdown解析庫(kù),下載是https://github.com/TooBug/wemark
接下來(lái)按照git上的教程集成wemark。
1、wxml引入
<import src="../../wemark/wemark.wxml"/>
<template is="wemark" data="{{...wemark}}"></template>
刪除原來(lái)的<view class="content">{{article.content}}</view>,因?yàn)椴辉儆玫剿恕?/p>
2、wxss引入
@import '../../wemark/wemark.wxss'
3、js中引入
var wemark = require('../../wemark/wemark');
然后設(shè)定數(shù)據(jù)
data: {
wemark: {}
},
再在請(qǐng)求Bmob成功回調(diào)里加上
// 渲染markdown
wemark.parse(result.get('content'), that, {
imageWidth: getApp().screenWidth - 20
})
效果如下
這個(gè)例子是比較簡(jiǎn)單的,但是做復(fù)雜的基礎(chǔ),諸如flex布局,data存儲(chǔ),navigate傳值,無(wú)限加載,可以說(shuō)是必然會(huì)用到的,對(duì)于沒(méi)有接觸過(guò)小程序開(kāi)發(fā)的朋友應(yīng)該是有借鑒意義的。