最近本身正作一個小程序,是基於小程序雲開發的,在作小程序項目的時候使用雲開發確實方即是不少。有關於雲開發後面我也會講到,畢竟這個項目就是使用的雲開發,更多的有關雲開發內容有須要的小夥伴能夠去看官方文檔,
雲開發文檔。
項目的開發也有一段時間了雖然只是實現了部分功能,可是我仍是忍不住來寫篇文章來分享一下這段時間的成果和項目中遇到的問題,後面我也會逐步的完善項目。項目源碼在github上,若是小夥伴們以爲不錯能夠給個star,仿頭條項目地址。
git
下面將詳細的介紹項目,雖然使用的雲開發節省了不少時間可是先後端的東西都須要作工做量有點大,在這短期內我沒有完成整個項目,只是實現了首頁,詳情頁,和登陸頁等主要功能
我首先將界面須要獲取數據的地方設計好數據庫爲後面數據的獲取作準備,數據庫使用的是小程序雲開發的MongoDB數據庫,將數據存儲在雲數據庫上,而且使用雲函數來操做數據庫github
首頁相對於詳情頁要簡單一些,在頭部使用了一個搜索框和搜索按鈕,而後下面是一個tab標籤欄含有多個標籤頁,每個標籤頁顯示標籤對應有關的新聞信。在標籤頁的右邊有一個按鈕,點擊按鈕會出現一個彈出框。這裏有個特別的地方,就是在推薦頁的頂部設置了一個置頂的新聞
數據庫
輸入框綁定了一個tap事件,使得在點擊輸入框但不輸入值的時候改變placeholder的值。
在tab欄的右邊有一個按鈕點擊按鈕將會出現一個彈出層,前面的gif中有演示,是新聞種類的選擇框,點擊關閉按鈕能夠關閉彈出層
最後就是首頁最重要的新聞顯示頁面了,爲了節省項目的時間,這裏使用了有讚的框架vant-weapp有興趣的小夥伴能夠去了解下。在tab標籤欄設置了6個標籤頁,可是隻會顯示4個標籤頁想要顯示其餘的能夠左右拖動標籤欄,這裏將推薦頁設置爲了默認激活的。因爲每一個每一個標籤頁代碼基本都相同的,只是在推薦頁是的第一欄是置頂信息,還有就是獲取的數據不一樣,有關數據獲取在下面介紹代碼將會細講,爲了提升代碼的複用,這裏使用了模板,將複用的代碼寫在寫在另外的文件下,使用時直接調用就能夠了。
每一個標籤對應都建立了一個集合,這裏我爲置頂新聞也另外建立了一個集合,而且給每條信息設計好須要用的字段方便本身獲取數據和使用數據,因爲雲數據庫是能夠導入json文件或者csv文件,而且每一個新聞也都須要上拉加載數據須要更多的數據,本身造數據費時間又麻煩,因此我這裏本身寫了爬蟲爬取本身須要的數據並保存到json文件中,直接將數據導入到數據庫中。
這樣設計數據庫也是使得從數據庫獲取數據方便了一些。寫一個module函數就能夠獲取每一個標籤的數據。
每條數據的字段以下,其中news_id起到很重要的做用,將首頁的每條新聞和對應的詳情頁面聯繫起來。
json
在每個標籤頁使用模板,而且設置了一個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的大小,當圖片沒有的時候就不會顯示圖片。app
不少在首頁講過的東西我在詳情頁也就再也不多說了,你們有不懂能夠去看源碼,畢竟講那麼多廢話就是浪費時間,我儘可能挑出最精彩的部分來寫。
在首頁的每一條新聞都綁定了一個跳轉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來判斷當前的評論是否含有圖片,有的話就將圖片顯示在評論中。這裏代碼我就不貼出來,有須要的能夠看源碼。
因爲項目有點大因此我在短期內只實現了部分功能,在後續的時間我會實現其餘功能。其實寫這個項目也是爲了實戰雲開發,同時我也體驗到了雲開發的好處。項目中有些不足的地方歡迎你們指出,有什麼好的建議也能夠聯繫我。你們相互學習