前言
最近自己正做一個小程式,是基於小程式雲開發的,在做小程式專案的時候使用雲開發確實方便是很多。有關於雲開發後面我也會講到,畢竟這個專案就是使用的雲開發,雲開發內容有需要的小夥伴也可以去看官方文件,
雲開發文件。
專案的開發也有一段時間了雖然只是實現了部分功能,但是我還是忍不住來寫篇文章來分享一下這段時間的成果和專案中遇到的問題,後面我也會逐步的完善專案。專案原始碼在github上,如果小夥伴們覺得不錯可以給個star,仿頭條專案地址。
專案詳解
下面將詳細的介紹專案,雖然使用的雲開發節省了很多時間但是前後端的東西都需要做工作量有點大,在這短時間內我沒有完成整個專案,只是實現了首頁,詳情頁,和登入頁等主要功能
我首先將介面需要獲取資料的地方設計好資料庫為後面資料的獲取做準備,資料庫使用的是小程式雲開發的MongoDB資料庫,將資料儲存在雲資料庫上,並且使用雲函式來運算元據庫
新聞首頁
首頁相對於詳情頁要簡單一些,在頭部使用了一個搜尋框和搜尋按鈕,然後下面是一個tab標籤欄含有多個標籤頁,每一個標籤頁顯示標籤對應有關的新聞信。在標籤頁的右邊有一個按鈕,點選按鈕會出現一個彈出框。這裡有個特別的地方,就是在推薦頁的頂部設定了一個置頂的新聞首頁介面
輸入框繫結了一個tap事件,使得在點選輸入框但不輸入值的時候改變placeholder的值。
在tab欄的右邊有一個按鈕點選按鈕將會出現一個彈出層,前面的gif中有演示,是新聞種類的選擇框,點選關閉按鈕可以關閉彈出層
最後就是首頁最重要的新聞顯示頁面了,為了節省專案的時間,這裡使用了有讚的框架vant-weapp有興趣的小夥伴可以去了解下。在tab標籤欄設定了6個標籤頁,但是隻會顯示4個標籤頁想要顯示其他的可以左右拖動標籤欄,這裡將推薦頁設定為了預設啟用的。由於每個每個標籤頁程式碼基本都相同的,只是在推薦頁是的第一欄是置頂資訊,還有就是獲取的資料不同,有關資料獲取在下面介紹程式碼將會細講,為了提高程式碼的複用,這裡使用了模板,將複用的程式碼寫在寫在另外的檔案下,使用時直接呼叫就可以了。
每個標籤對應都建立了一個集合,這裡我為置頂新聞也另外建立了一個集合,並且給每條資訊設計好需要用的欄位方便自己獲取資料和使用資料,由於雲資料庫是可以匯入json檔案或者csv檔案,並且每個新聞也都需要上拉載入資料需要更多的資料,自己造資料費時間又麻煩,所以我這裡自己寫了爬蟲爬取自己需要的資料並儲存到json檔案中,直接將資料匯入到資料庫中。
這樣設計資料庫也是使得從資料庫獲取資料方便了一些。寫一個module函式就可以獲取每個標籤的資料。
每條資料的欄位如下,其中news_id起到很重要的作用,將首頁的每條新聞和對應的詳情頁面聯絡起來。
具體功能實現
在每一個標籤頁使用模板,並且設定了一個data(給不同頁面傳入需要顯示的對應新聞資訊,用於在頁面顯示),由於預設啟用頁面是推薦頁所以在onload事件觸發時將預設載入推薦頁的資料,同時將推薦頁設定為已被啟用頁面,資料載入這裡寫了一個載入函式
module: function(title) {
let counter = this.data.counter
// console.log(title)
wx.cloud.callFunction({
name: 'module',
data: {
counter: counter,
title: title
}
}).then(res => {
// console.log(res)
let cnews = this.data.cnews
let data = res.result.data
// console.log(data)
for(let i = 0; i < data.length; i++) {
// console.log(data[i].date)
data[i].date = data[i].date.slice(0, 10)
cnews.push(data[i])
this.imgCheck(data[i].images, data.new_id, title)
}
// console.log(data)
this.setData({
hiddenLoading: true,
cnews: cnews,
counter: counter+1
})
})
}
複製程式碼
傳入一個title就是當前顯示的標籤的標題,預設的是推薦,使用一個counter計數,每次只會載入5條新聞條資料,從資料庫獲取新聞的資訊是由一個雲函式來解決的
#### 通過雲函式獲取資料
// 雲函式入口檔案
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
// 雲函式入口函式
exports.main = async (event, context) => {
return await db.collection(event.title).skip((event.counter-1)*5).limit(5).get()
}
複製程式碼
給雲函式傳入兩個資料,一個是title就是從對應集合獲取資訊,還有一個就是counter用來計算獲取資訊的位置,因為,在向上拉取載入更多新聞的時候需要載入資料,我這裡設定每次載入5條資料,所以傳遞給雲函式一個counter,每次呼叫了雲函式從與資料庫獲取一次資料counter就會+1,從而使得每次上拉載入資料時忽略已經載入的資料從後面載入資料。每次載入資料都會更新一次儲存資料的陣列,在主頁的index.wxml頁面將會判斷並獲取資料使用一個for迴圈將資料顯示到對應的標籤頁
下拉重新整理
在置頂新聞那部分在資料獲取的資料其實也沒很特別,我只是將置頂新聞集合中最新的新聞從雲資料庫拿下來,然後展示頁面中
這裡也實現了下拉重新整理,使用了小程式的onPullDownRefresh函式下拉重新整理將會獲取最新的資料,並且將最新的資料插顯示在最上部分,由於每次下拉需要插入資料到集合的前面,所以我這裡顯示不明顯
onPullDownRefresh: function () { // 監聽下拉動作來獲取最新新聞資訊
wx.showToast({
title: '推薦中',
image: '../../../image/載入.png'
})
let title = this.data.title;
wx.cloud.callFunction({
name: 'module',
data: {
counter: 1,
title: title
}
}).then(res => {
// console.log(res)
let cnews = this.data.cnews
let datas = res.result.data
let data = datas.concat(cnews)
this.setData({
hiddenLoading: true,
cnews: data,
})
})
}
複製程式碼
圖片鑑定
在module函式有使用了一個圖片鑑黃功能,使用了騰訊的一個圖片識別介面,畢竟不是什麼圖片都能顯示出來,所以寫了一個imgCheck函式來檢測每一條新聞的所有圖片,當圖片不合格的時候則將這條新聞刪除。我沒有使用圖片去測試,更不可能展示出來是吧,相信大家都懂(猥瑣笑)。
當不同標籤頁進行切換的時候會有一個onchange事件,onchange事件會獲得title和index。並且將onchange之後的資料儲存到一個陣列中,在onchange事件裡面使用module函式來獲取對應的title的資料並且判斷這條資料是否是最近載入過的,如果是上次onchange事件載入過的函式將會顯示上次事件儲存的資料,在wxml中也會判斷是否是上次啟用的頁面來顯示對應的資料。
前面一直再講後端的東西,我也這篇文章也是為了講雲開,說實話有了雲開發真的方便了很多,一個人就可以搞定前後端的東西。不過為了方便大家的理解,我還是講一下介面的內容。
既然前都已經將資料拿過來了,最後要做的就是將資料展示出來了,每條資料
<van-tab title="推薦" >
<!-- 推薦tab標籤頁的置頂新聞框 每一個新聞框可以點選進入到詳情頁-->
<van-panel class="topping" title="{{topTitle}}" status="置頂" use-footer-slot bind:tap="showTopDetail" data-item="{{topNew_id}}">
<view class="images">
<image src="{{images[0]}}" />
<image src="{{images[1]}}" />
<image src="{{images[2]}}" />
</view>
<view solt="footer" class="footer">
<view class="author">{{topAuthor}}</view>
<view class="comment">評論{{topComment}}</view>
<view class="Date">{{topDate}}</view>
</view>
</van-panel>
<template is="container" data="{{news: active1 == 'news'?news:cnews, hiddenLoading}}"></template>
</van-tab>
複製程式碼
<template name="container">
<view class="container">
<loading hidden="{{hiddenLoading}}"></loading>
<view class="news" wx:for="{{news}}" wx:for-item="info" wx:key="info.new_id">
<van-panel class="new" title="{{info.title}}" bind:tap="showDetail" use-footer-slot data-item="{{info.new_id}}">
<view class="images" wx:if="{{info.images.length > 0}}">
<image src="{{info.images[0]}}"/>
<image src="{{info.images[1]}}"/>
<image src="{{info.images[2]}}"/>
</view>
<view solt="footer" class="footer">
<view class="author">{{info.author}}</view>
<view class="comment">評論{{info.comments}}</view>
<view class="Date">{{info.date}}</view>
</view>
</van-panel>
</view>
</view>
</template>
複製程式碼
這裡用的就是MVVM思想,將資料繫結到UI介面,在js檔案中獲取到資料後,這裡將資料拿過來使用。
這裡由於每條新聞的圖片數量是不確定的,並且最多隻顯示三張圖片。所以直接固定了3個image標籤並且固定了image的大小,當圖片沒有的時候就不會顯示圖片。
詳情頁
很多在首頁講過的東西我在詳情頁也就不再多說了,大家有不懂可以去看原始碼,畢竟講那麼多廢話就是浪費時間,我儘量挑出最精彩的部分來寫。
首頁轉詳情頁
在首頁的每一條新聞都繫結了一個跳轉tap事件,當點選新聞後將會跳轉到詳情頁,並且將新聞的id和title作為引數傳給詳情頁。
showDetail: function(e) { // 點文章顯示文章詳情
let item = e.currentTarget.dataset.item;
let title = this.data.title;
// console.log(e)
wx.navigateTo({
url:`../detail/detail?contentId=${item}&title=${title}`
})
}
複製程式碼
介面
在點選跳轉到詳情頁後,將會在onload的事件中獲取到對應的新聞id,並將id存到data裡面。由於在爬取詳情頁的時候沒有爬下來,所以我隨便將一些簡單的內容放在content裡面。
詳情頁這部分我將頁面分為了內容部分和評論。然後還有就是使用了一個fixed將輸入框等按鈕固定在螢幕底部
內容部分又分為了四部分,分別是標題部分,作者頭像和暱稱,內容部分,點贊轉發部分,將資料庫中的資料展示顯示到介面。
第二部分為顯示像和暱稱我使用了一個flex的浮動佈局將並且將暱稱部分的flex設定為1使得頭像和關注按鈕分別在兩邊。頭像使用了一個image標籤並且將image標籤的大小固定,畢竟使用者上傳的圖片肯定大小不一樣。第四部分只要使用4個view在把圖片和內容放進去再使用一個flex佈局就可以搞定。
功能具體實現
既然介面佈局已經搞定現在就是要拿資料了,在點選新聞進入來詳情頁的時候會的到新聞的id和title,這樣可以通過唯一id(每條doc的id)的和title(集合的名字)從雲資料庫拿出對應新聞資料。這裡程式碼就不貼出來了,跟前面首頁的差不多,有需要的可以去github看原始碼。
接下來就是評論部分的內容了,個人認為這個地方還是挺有趣而且在更新資料庫的時候還有許可權問題,前面沒有講這個問題就是打算放到評論部分一起來講。 在頁面的底部固定了一個評論框,包含輸入框,跳轉到評論的按鈕,收藏按鈕,轉發按鈕。
點選轉發按鈕會出現一個彈窗,可以選擇需要轉發到的渠道,並且給彈出層背景新增了蒙層效果,只有在點選蒙層或者取消按鈕彈出框才會消失。這裡只實現了轉發到微信的功能,只需要呼叫一下微信小程式的onShareAppMessage介面就可以搞定,當點選微信的圖示後可以轉發給朋友或者微信群。 收藏按鈕我就是用了一個wx:if來判斷顯示的是那個image點選一個隊bool值取反。 點選評論按鈕可以從直接跳轉到評論的頂部,使用一個scrollview將整個詳情包裹住然後 使用它的一個屬性scroll-into-view當點選底部的評論按鈕時將評論部分的id賦值給scroll-into-view就可以實現錨點跳轉了。在這個地方我踩了一個坑,沒有給scroll-into-view設定一個高度導致效果一直出不來,由於詳情頁需要評論頁面高度是改變的,所以直接給它設定一個100vh就可以完美搞定這個地方的錨點跳轉了。
最後就是輸入框了點選輸入框或者左邊的輸入按鈕就可以彈出評論輸入框了,當輸入框內有值的時候釋出按鈕會改變顏色。當未授權登入將無法釋出評論 這裡就需要在我的頁面點選登入進行授權,獲取獲取使用者資訊。
登入功能的實現在頁面登入按鈕設定屬性為open-type=getUserInfo,bindgetuserinfo=getUserInfo 點選登入按鈕授權登入將會獲取使用者資訊,並將使用者資訊儲存到全域性上,這樣在詳情頁面便可以判斷或者使用使用者資訊。 授權就可以釋出新聞評論了,由於在登入的時候獲取到了使用者使用,所以在評論的是就有使用者avatar和nickname。當在評論輸入框中輸入了值並且使用者授權了登入的時候點選發布,同時將資料儲存到資料庫中。下面就是評論功能函式
submit: function() { // 實現評論功能,將釋出的評論同步到雲資料庫
let value = this.data.inputValue;
let new_id = this.data.new_id;
let userInfo = this.data.userInfo
// let new_id = '6594157273642172936'
if(userInfo){
comments.where({
new_id: new_id
}).get({
success: (res) => {
// console.log(res)
let comms= res.data[0].comments;
let people = {
content: value,
like: 0,
avatar: userInfo.avatarUrl,
nickname: userInfo.nickname
}
comms.unshift(people);
// console.log(comm)
this.setData({
comms: comms,
input: '',
})
wx.cloud.callFunction({
name: 'updateComments',
data: {
new_id: new_id,
comms: comms
}
}).then(res =>{
console.log(res)
})
}
})
}
}
複製程式碼
評論部分的資料庫我只建立了一個comments集合,開始的新聞new_id就起到作用了,每一comment都有一個new_id,新聞的每一條評論就是設定為一個物件,畢竟評論還包括頭像暱稱,點贊數,評論內容等。這樣設定評論資料庫好處就是,只要獲取新聞id在一個集合中就可以獲取到新聞對應的評論。
開始在更新資料庫的時候我沒有使用雲函式,而是在js中直接更新資料,獲得返回資訊顯示是請求成功但是update數為0,但是當我到資料庫中檢視是發現資料並沒有更新成功,查了一下文件發現是許可權的問題,因為資料的修改只能是管理者或者資料的建立者,而資料又是我自己手動輸入到雲資料庫的,在js中直接更新的資料庫的時候不是建立者而在小程式端又沒有管理者許可權,所以沒有許可權修改資料。既然無法是建立者想要修改資料只能是管理員了,所以這裡我使用了雲函式來修改資料。說到這裡大家應該意識到了雲函式的許可權是什麼級別了吧,這裡給大家看下官方文件的說明。 雲函式也不能隨便亂用,畢竟許可權最大。更具體的內容可以去細看官方文件既然可以評論那就少不了點贊功能吧,雖然點贊是很普通的功能但是這裡涉及到了雲資料而且具體實現還是很有趣的。
每條評論都可以點贊一次再次點選時將會取消點贊。評論部分的點讚我這裡寫的addLike函式繫結到點贊按鈕,由於每條評論都繫結了相同的點贊函式,所以需要區分是那條評論被點贊所以給每條評論設定了data-item="{{index}}"i(index是在使用for迴圈展示評論使所產生的)同時對應了評論在資料庫儲存的位置,這樣一來就方便來區分被點讚的那一條評論了。
當被點贊後點贊按鈕將換為紅色的按鈕,同時資料庫中like也要加一。再次點贊按鈕則還原,like也將還原。其實點贊功能還是很有趣的,這完全是我個人的想法,可能還有不好的地方,但是我還是推薦大家看一下。下面就是具體實現的程式碼
addLike: function(e) { // 點選點贊圖示增加點贊數同時儲存到資料庫
let item = e.currentTarget.dataset.item;
let new_id = this.data.new_id;
let comms = this.data.comms;
let likeItem = this.data.likeItem;
let likebool = 'likeItem['+item+'].bool'
let liken = 'likeItem['+item+'].n'
if(typeof(likeItem[item]) == "undefined"){
this.setData({
[likebool]: false,
[liken]: 0,
})
}
if(likeItem[item]){
likeItem[item].n += 1;
if(likeItem[item].n%2){
comms[item].like += 1;
}else{
comms[item].like -= 1;
}
likeItem[item].bool = !(likeItem[item].bool);
}else{
likeItem[item].bool = true;
likeItem[item].n = 0;
comms[item].like += 1;
}
this.setData({
comms: comms,
likeItem: likeItem
})
// console.log(comms)
wx.cloud.callFunction({
name: 'updateComments',
data: {
new_id: new_id,
comms: comms
}
}).then(res =>{
// console.log(res)
})
},
複製程式碼
在評論輸入框的下邊欄有一個核取方塊按鈕,圖片按鈕等這裡我使用了了flex佈局輕鬆搞定,這是我實現了下評論插入圖片功能,同時將圖片儲存到雲端。其實評論插入圖片還需要優化,我在寫完文章後也還會繼續優化。
我這是使用了小程式雲開發的一個檔案上傳介面wx.cloud.uploadFile,將圖片上傳後會生成一個fileID,我將fileID(也就是圖片地址)儲存到當前評論物件的image下,同時更新本地的資料,再通過一個if來判斷當前的評論是否含有圖片,有的話就將圖片顯示在評論中。這裡程式碼我就不貼出來,有需要的可以看原始碼。
總結
由於專案有點大所以我在短時間內只實現了部分功能,在後續的時間我會實現其他功能。其實寫這個專案也是為了實戰雲開發,同時我也體驗到了雲開發的好處。專案中有些不足的地方歡迎大家指出,有什麼好的建議也可以聯絡我。大家相互學習