做者:知曉雲 - 小程序開發快人一步css
前面咱們搭建了一個簡單的頁面框架,實現了文章列表展現和跳轉文章詳情的功能。然而,僅有這些功能是明顯不夠的,所以,接下來,我將向你講解,如何加上更多稍顯複雜,但頗有必要的功能,包括加載更多文章列表,顯示未讀與已讀狀態和文章分享。數據庫
前面,咱們在首頁模擬了獲取第一頁文章的請求。考慮到性能問題,大部分狀況下咱們不會在首頁展現出全部的文章列表,在 PC 上咱們能夠經過分頁來實現,而在移動端,比較常見的作法是在列表末尾經過上拉或者一個加載更多按鈕,來獲取更多文章。這裏,咱們將採用第二種作法。編程
加載更多的邏輯是這樣的:當一次請求獲取到的文章數量大於或等於咱們規定的每頁數量時,按鈕的文案會顯示爲 」加載更多「,而且點擊後會去獲取下一頁的文章,而若是獲取到的文章數量小於咱們規定的每頁數量時,按鈕的文案會顯示爲 」已無更多「。小程序
這裏須要解釋一下,若是獲取到最後一頁的文章數剛好爲咱們規定的每頁數量時,當點擊加載更多,會繼續獲取下一頁文章,此時獲取到的文章數量爲 0 ,小於規定的每頁數量,按鈕的文案變爲 」已無更多「。數組
爲了簡化步驟,咱們模擬的下一頁的文章數量小於 4 篇,這樣,當咱們點擊一次加載更多後,按鈕文章會變爲 」已無更多「。緩存
這裏咱們須要增長兩個變量,一個是 isEnd,用於標識已無更多,另外一個是 isLoading,用於防止用戶連續屢次點擊加載更多按鈕。bash
經過小程序中的按鈕組件的 loading 屬性,能夠方便地顯示正在加載中的樣式。app
// pages/index/index.wxml
<button type="default" plain="{{true}}" loading="{{loading}}" bindtap="loadMore">
{{loadMoreText}}
</button>
複製代碼
製造靜態數據,數量爲 2 條,表示已無更多。框架
// pages/index/index.js
const lastPage = [{
id: '5',
title: '超新約全書',
description: '一個以折磨人爲樂趣的上帝',
cover: 'https://xxx.xxx.xxx.jpg'
}, {
id: '6',
title: '2001太空漫遊 2001',
description: '現代科幻電影技術的里程碑',
cover: 'https://xxx.xxx.xxx.jpg'
}]
// pages/index/index.js
let isEnd = false
Page({
data: {
articles: [],
loading: false,
loadMoreText: '加載更多'
},
onLoad: function() {
this.getArticles(true)
},
loadMore: function(event) {
this.getArticles()
}
})
複製代碼
從新實現 getArticles 方法:異步
getArticles: function(isFirstPage) {
if (!isEnd && !this.data.loading) {
this.setData({ loading: true })
setTimeout(() => {
if (isFirstPage) {
this.setData({
articles: firstPage,
loading: false
})
} else {
this.setData({
articles: firstPage.concat(lastPage),
loading: false
})
if (lastPage.length < pageLimit) {
isEnd = true
this.setData({ loadMoreText: '已無更多' })
}
}
}, 1000)
}
}
複製代碼
每一次獲取到新的頁面時,咱們經過 Array.concat 方法,將它拼接入到以前的文章列表後面,而後進行 setData 。這樣,咱們就實現了加載更多文章列表的功能了。
有時候,咱們也會忘了本身曾閱讀過某篇文章,雖然對於大多數人來講這並不常見,但對於我這種記憶力不是很好的人來講,這事情發生的頻率仍是很大的。因此,我有必要爲本身提高一下用戶體驗。
當用戶在首頁點擊了某個文章列表項後,咱們須要將該列表項的文字顏色設置爲灰色,正常狀況下,他們是黑色的。
爲了標記用戶是否讀過某篇文章,咱們在用戶點擊某篇文章的同時,將其文章 id 保存起來。相似這種數據,咱們通常不會保存到數據庫,由於有點牛刀小試了,咱們只須要將數據保存到本地便可,只要用戶不清緩存數據就不會丟失,即便請了緩存,丟失了數據,也並不會形成多大的損失。
接下來,讓咱們看看如何在小程序中使用本地存儲吧。
小程序提供了兩種方法讓咱們操做本地存儲,包括同步操做與異步操做。
同步:
添加:wx.setStorageSync
獲取:wx.getStorageSync
異步:
添加:wx.setStorage
獲取:wx.getStorage
關於同步和異步的區別,有個例子很好地作了說明:
同步調用就是你喊你的朋友吃飯,你朋友在忙,你就一直在那等,等你朋友忙完了,大家一塊兒去。
異步調用就是你喊你的朋友吃飯,你朋友說知道了,待會忙完去找你,你就去作別的事了。
可見,異步調用的效率會比同步好,但應用到編程語言上,就要稍微多寫點代碼了。以獲取 key 爲 id 的數據爲例,咱們講解一下這兩種調用方式分別是如何使用的:
同步:
var value = wx.getStorageSync('key')
console.log('id', value)
複製代碼
異步:
wx.getStorage({
key: 'id',
success: function(res) {
console.log('id', res.data)
}
})
複製代碼
能夠看到,使用同步操做相對於異步操做更簡單也更簡潔一點,異步操做主要是用在對性能有要求的場景,這裏爲了操做方便,咱們將使用同步操做來實現該功能。
在前面的基礎上,咱們在每一個 article 數據中再加入一個 isReaded 字段,用於標識該文章是否已被閱讀。
當用戶在首頁點擊某一篇文章時,要先判斷 storage 中是否有 key 爲 READED_ARTICLES (字符串常量)的記錄,若是沒有,則建立該記錄,其 value 爲數組,並將該文章的 id push 到該數組中。若是已存在名爲 READED_ARTICLES 的記錄,則判斷該文章的 id 是否包含在其 value (數組類型)中,不存在則 push ,存在則跳過。
// pages/index/index.js
toDetailPage: function(e) {
let id = e.currentTarget.dataset.id
let readedArticles = wx.getStorageSync(READED_ARTICLES)
if (!readedArticles) {
wx.setStorageSync(READED_ARTICLES, [id])
} else if(readedArticles.indexOf(id) == -1) {
readedArticles.push(id)
wx.setStorageSync(READED_ARTICLES, readedArticles)
}
this.setData({articles: this.addReadStatus(this.data.articles)})
wx.navigateTo({
url: `../detail/index?id=${id}`
})
}
複製代碼
上面,咱們在 setData 的時候再也不使用 this.data.articles,而是使用 this.addReadStatus(this.data.articles),addReadStatus 是咱們本身定義的方法,它接受一個 articles 參數,並根據 localStorage 中保存的,已閱讀過的文章的 id ,來給文章添加 isReaded 屬性。
addReadStatus: function(articles) {
let readedArticles = wx.getStorageSync(READED_ARTICLES)
if (!readedArticles) {
return articles
}
let newArticles = []
for (let i = 0; i < articles.length; i++) {
let article = Object.assign(articles[i])
if (readedArticles.indexOf(article.id) != -1) {
article.isReaded = true
} else {
article.isReaded = false
}
newArticles.push(movie)
}
return newArticles
}
複製代碼
同時,咱們不要忘了另外一種狀況,當用戶從新打開小程序的時候,咱們也須要給文章加上 isReader 屬性。即在 getArticles 方法中的 setData 裏使用 addReadStatus,以下:
// pages/index/index.js
this.setData({
articles: oldArticles.concat(this.addReadStatus(data)),
loading: false
})
複製代碼
有了 isReader 作標誌,咱們就不難爲不一樣狀態的文章加上不一樣的樣式了。
// pages/index/index.wxml
<button type="default" plain="{{true}}" loading="{{loading}}" bindtap="loadMore">
{{loadMoreText}}
</button>
複製代碼
到這裏,咱們就完成了一個有點複雜,但又很實用的小功能了。接下讓咱們再開發一個能夠提升咱們應用活躍度的功能——分享。
分享基本上是每一個應用都必不可少的功能,在小程序中實現一個常規的分享功能,是再簡單不過了,但簡單也意味着不夠特別,若是你想要得到更多的分享量,那就須要在分享方式上下點功夫了。
接下來我將介紹兩種方式來實現分享功能,一種是最常規的也是最普通的,點擊右上角的菜單,使用彈出的菜單項中分享菜單項。 另外一種方法是自定義一個分享按鈕,用戶點擊按鈕後即彈出確認分享框,該方法靈活性強,而且比第一種少操做了一步。好了,讓咱們開始吧。
不管使用菜單仍是自定義控件來實現分享功能,都須要咱們在要加入分享功能的 Page 中實現 onShareAppMessage(options) 方法,在該方法中設置該頁面的轉發信息和轉發成功或失敗的回調。
Page({
onShareAppMessage: function (options) {
return {
title: '標題',
path: '/page/user?id=123',
success: function() {
// 轉發成功
console.log(`share by: ${options.from}`)
},
fail: function() {
// 轉發失敗
}
}
}
})
複製代碼
options 參數說明:
使用菜單中的分享功能,咱們只需在 page 中定義 onShareAppMessage 便可。
// pages/detail/index.js onShareAppMessage: function (options) { return { title: this.data.article.title, imageUrl: this.data.article.poster, path: pages/detail/index?id=${id}
, } }
與使用菜單中的分享功能同樣,咱們一樣要實現 onShareAppMessage 方法。自定義分享組件,咱們須要藉助到 button 組件的 open-type 屬性,將其設置爲 "share" ,當點擊按鈕便會彈出分享確認框。
<button open-type="share">分享<button/>
複製代碼
到這裏不少人會有疑惑了,難道咱們必須使用 button 組件才能實現自定義分享組件嗎?button 組件那麼醜……。很遺憾,咱們的確須要使用 button 組件,但也不用那麼失望,雖然咱們要使用 button 組件,但誰說 button 組件就醜了呢,咱們還有 css 的嘛。如今,咱們就藉助 css ,實現一個懸浮於屏幕右下角,圓形的,帶背景圖片的分享按鈕。
<button plain="{{true}}" open-type="share" />
// pages/detail/index.wxss
.article-share-btn {
position: fixed;
right: 30rpx;
bottom: 30rpx;
width: 70rpx;
height: 70rpx;
background-image: url("https://cloud-minapp-1131.cloud.ifanrusercontent.com/1eNFg1HrAVjWkrNQ.png");
background-size: 70rpx 70rpx;
border: 0 !important;
}
複製代碼
最後的效果以下:
到這裏,咱們就搭建起了一個文章展現小程序基本的頁面框架,同時爲其加上了一些很實用的小功能,你也能夠閱讀小程序官方文檔,找找那些你感興趣的功能的小程序 API ,來豐富你的小程序功能吧。
相關閱讀
第一章:一文了解小程序