Day10-微信小程式實戰-交友小程式-新增好友功能之建立並更新message資訊
1、首先要在 新增好友 這個按鈕上新增一個事件,也就是在detail.wxml的新增好友這個按鈕的哪裡,新增一個點選事件 handleAddFriend
並且新增好友還要考慮,現在是已登陸狀態還是未登陸狀態的,只有是登陸狀態的時候,才可以發起新增好友的請求的
所以就要先判斷一下它是否已經登陸了
因為只要是登陸之後,就會把使用者的id寫入到全域性的userinfo下面的
handleAddFriend(){ if( app.userInfo._id){ } else{ wx.showToast({ title: '請先登陸', duration : 2000, // 然後不要讓它顯示圖示 icon : 'none', success: ()=>{ // 如果成功的話就直接跳轉到我的頁面去 // 但是注意了這裡不能用 navigator to,因為它主要是跳轉 // 普通的頁面,而這裡“我的頁面”其實是同tabbar來進行配置的 } }) } }
這個時候就可以查詢一下 小程式文件 中關於“路由”的介紹了
可以看到要用wx.switchtab來進行操作了
然後因為我們設定了那個提示“請先登陸”是維持兩秒鐘,所以我們也要設定這個跳轉到我的頁面中的時間也是兩秒鐘
handleAddFriend(){ if( app.userInfo._id){ } else{ wx.showToast({ title: '請先登陸', duration : 2000, // 然後不要讓它顯示圖示 icon : 'none', success: ()=>{ // 如果成功的話就直接跳轉到我的頁面去 // 但是注意了這裡不能用 navigator to,因為它主要是跳轉 // 普通的頁面,而這裡“我的頁面”其實是同tabbar來進行配置的 setTimeout(()=>{ wx.switchTab({ url: '/pages/user/user', }) } , 2000); } }) } }
上面的加入 沒登陸的情況也寫好了,下面就是對已經登陸了之後的設計了
就要在資料可以中建立一個message集合,主要是用來儲存好友訊息,或者是系統的訊息給這個使用者的一個資訊集合的
這個集合裡面的每一個資訊,包含了userID也就是這個好友請求或者是資訊是傳送給哪一個人的
然後還有一個其他想要加他好友的使用者id list陣列,因為每個人都可以給這個人發起好友請求的,這就是對於資料庫1的建立了
所以在已經登陸之後,先檢視一下有沒有這個發起好友的資訊了,如果還有的話,就在資料庫中創立這個欄位了
這個資料庫裡面的userid欄位存的其實就是我們要加的這個人的id標識了,然後這個人的id我們可以從這個人的詳情頁面(detail)下的data中來獲得的
通過where就可以定位到在資料庫中這個使用者對應的欄位了,然後用get就可以開始對這個欄位裡面的東西進行查詢了
如果這個資訊已經存在了就做更新操作,如果不存在的話就做建立操作即可了
if( app.userInfo._id){ db.collection('mesasge').where({ userId : this.data.detail._id }).get().then((res)=>{ if( res.data.length){//更新 } else{ //tianjia1 db.collection('message').add({ data : { userId : this.data.detail._id, list : [ app.userInfo._id] } }) } }); }
之後就可以檢視資料可以中的message 集合
這樣的話,說明就呼叫成功了
二、更新message 資訊
因為如果已經申請過了的話,就不能再往list裡面新增自己的id了,所以就要檢測一下現在是否在list中,
可以直接呼叫陣列的include方法來進行查詢,如果找到了的話,就提示“已申請過了”如果沒找到的話就要往這個數組裡面進行資料更新了
查看了微信開放文件之後會發現,如果是單個數據進行更新的話可以直接用doc好到之後進行更新就好了,但是如果對大量的資料進行批量的更新的話
因為在客戶端的更新能力還是有限的,所以就要到服務端上來完成了,也就是用雲函式來完成了(其實這個方法我們已經寫好了,也就是雲函式update了
else{ wx.cloud.callFunction({ // name也就是我們要修改的資料庫的名字,data就是在雲函式中 // 想要的引數了 name : 'updata', data : { collection : 'message', where :{ userId : this.data.detail._id }, data : { } } }) }
注意了,在呼叫雲函式的時候,前面的data和後面的data是不一樣的,錢買你的是給雲函式的引數,但是後面的是我們要修改的資料了
在要修改list的資料到時候,就涉及了要對陣列進行新增,也就是push操作了,其實在資料可以中也內建了一些的方法,commend.push等等
注意:在detail.js檔案中,如果找到了這個資料流,但是沒有申請的話,就是進行更新,在更新的時候用到了update雲更新函式,
給這個雲函式傳入的data中
data : `{list : _.unshift(' ${app.userInfo._id} ')}`
注意:最外面那層 並不是 單引號,而是 鍵盤 Esc下面的那個標點
三、新增好友功能之監聽message訊息
在資料庫加入了一個 帶有list和userid的資料,所以在userid這個人登陸小程式之後,就應該可以看到有沒有人給他傳送訊息了
並且還是要實時的更新,就是這個人在登陸狀態的話,也可以直接收到了,也就是要實現實時的監聽資料庫中list的實時變化了
在開發者文件中:雲開發-》實時資料的推送:
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/realtime.html
(它的意思就是我們可以監聽到資料庫傳送的變化
可以直接檢視demo
const db = wx.cloud.database() const watcher = db.collection('todos') // 按 progress 降序 .orderBy('progress', 'desc') // 取按 orderBy 排序之後的前 10 個 .limit(10) .where({ team: 'our dev team' }) .watch({ onChange: function(snapshot) { console.log('docs\'s changed events', snapshot.docChanges) console.log('query result snapshot after the event', snapshot.docs) console.log('is init data', snapshot.type === 'init') }, onError: function(err) { console.error('the watch closed because of error', err) } }) // ... // 等到需要關閉監聽的時候呼叫 close() 方法 watcher.close()
我們可以在user頁面中進行檢測即可,也就是在登陸之後進行檢測了
我們建立了一個方法 getMessage()。只要使用者登陸了之後就可以進行觸發了,在onReady裡面的登陸成功程式碼之後即可了
也就是在資料庫定位到uuseid是這個使用者的資料之後,得到了之後就可以用watch方法來進行監聽了
getMessage(){ db.collection('message').where({ userId : app.userInfo._id }).watch({ onChange: function (snapshot) { console.log(snapshot); } }); }
這個onChange就是進行監聽的函數了,我們在遇到陌生的一定要傳入引數的函式的時候,最好是把這個引數用console.log打印出來看看我們的想要的資料在哪個位置裡面的
注意了:如果是按照上面這樣的話,是會報錯的,以為缺少了錯誤返回的 onError函式的,示例的demo裡面的格式是怎麼樣的,最好就用怎麼樣的
不然可能都是會報錯的
但是會發現,我們沒拿到有用的資料
就可以用多賬號來除錯一下了
(這裡用的多賬號最好還是用真實的賬號把,因為虛擬的出現的問題挺大的)
(然後還要設定給message許可權是第一個,允許全部人看的那種,才可以看到在別的賬號上的加好友資訊的
在別的賬號上面的話就可以看到列印的資訊了,可以看到我們得到的訊息其實是挺亂的,所以最好用判斷來搞一下
測試之後會發現,得到的 snapshot 資料中有一個 docChanges 陣列的,只要有申請,就會有顯示了
所以我們可以通過對陣列的長度進行一個判斷
然後再對這個list進行判斷,通過長度來進行判斷,如果有長度的話說明就有訊息了
有訊息的話就要給使用者一個提示,就是在下面的tabbar中的訊息圖示右上角新增一個紅色的小點
===其實這個功能在微信小程式中其實就已經幫我們設計好了
微信文件-》API-》介面-》tabbar-》wx.showTabBarRedDot
https://developers.weixin.qq.com/miniprogram/dev/api/ui/tab-bar/wx.showTabBarRedDot.html
它需要定義一個index屬性,來指定放紅點的是tabbar中的哪一項的(它是從0開始的,所以我們設定為2即可了)
也就是說這個使用者拿到了這個list之後,通過這個list的長度來判斷有沒有訊息,然後設定紅點提示,並且還要把這個得到的list用到訊息頁面中去的
所以就涉及到了,怎麼把這個得到的list共享到訊息中去,這個和之前的userInfo是類似的,點開全域性的app.js
this.userMessage = []
這裡創立的是一個數組來的,不是物件了
然後在user.js裡面,判斷這個得到的list的長度,設定tabbar上面的小紅心,然後把得到的list賦值給全域性的userMessage
但是如果檢測到這個list是空的話,就要把在tabbar上面的小紅心取消掉了
**然後還要讓我們全域性的userMessage等於一個空的陣列即可了
這樣,這個監聽的函式就完成了:
getMessage(){ db.collection('message').where({ userId : app.userInfo._id }).watch({ onChange: function (snapshot) { // console.log(snapshot) if( snapshot.docChanges.length){ //這裡就可以直接拿到message裡面所對應的訊息列表了 let list = snapshow.docChanges[0].doc.list; if( list.length ){ wx.showTabBarRedDot({ index: 2, }); app.userMessage = list; } else{ wx.hideTabBarRedDot({ index: 2, }) app.userMessage = []; } } }, onError: function (err) { console.error('the watch closed because of error', err) } }); }
然後因為watch是實時監聽的,我們在資料庫裡面把給的資訊刪掉的話
這個紅點也就會消失了
這就是因為正在實時的監聽著
四、下面搞的就是如何把共享的userMessage在訊息頁面中渲染出來
===訊息頁面和removeList元件佈局
首先 切換編譯模式到訊息頁面中,先做佈局
<view class="message"> <view> <text>暫無訊息:</text> </view> <view> <text>訊息列表:</text> <view>第一條訊息</view> <view>第二條訊息</view> </view> </view>
之後就是先判斷有沒有訊息。所以就要在js看i嗎新增一個東西,這裡新增的是一個userMessage陣列,就是用來接收我們的那個全域性的list的,
如果這個陣列是空的話,說明就是沒有訊息了,反之,所以就可以通過這個來進行判斷了
**之後就要測試一下message這個頁面裡面檔案的生命週期了
這就是為了測試,在tabbar中的生命週期是怎麼樣的
在message.js裡面
onReady: function () { console.log(1) }, /** * 生命週期函式--監聽頁面顯示 */ onShow: function () { console.log(2) },
在點選了下main的tabbar的圖示之後,
列印的結果:
但是當我們幾點了個人頁面之後,再點選訊息頁面的時候,只打印了2
也就是說在tabbar裡面的onreay並不會再次的觸發(但是普通頁面的onreay是會被再次觸發的),但是他也是會觸發onshow的
所以基於這個就可以在onshow中新增東西,來監聽現在的訊息變化情況了
因為如果想要進入訊息頁面的話,就得先登陸,所以這力又要一個判斷了,如果沒登陸得話,就讓他跳轉到登陸頁面去的
(這個功能就和我們的detail裡面很像的,就可以直接COPY過來了)
const app = getApp() Page({ /** * 頁面的初始資料 */ data: { userMessage : [], logged : false }, /** * 生命週期函式--監聽頁面載入 */ onLoad: function (options) { }, /** * 生命週期函式--監聽頁面初次渲染完成 */ onReady: function () { // console.log(1) }, /** * 生命週期函式--監聽頁面顯示 */ onShow: function () { // console.log(2) if( app.userInfo._id ){ this.setData({ logged : true, userMessage : app.userMessage }); }else{ wx.showToast({ title: '請先登陸', duration: 2000, // 然後不要讓它顯示圖示 icon: 'none', success: () => { // 如果成功的話就直接跳轉到我的頁面去 // 但是注意了這裡不能用 navigator to,因為它主要是跳轉 // 普通的頁面,而這裡“我的頁面”其實是同tabbar來進行配置的 setTimeout(() => { wx.switchTab({ url: '/pages/user/user', }) }, 2000); } }) } }, /** * 生命週期函式--監聽頁面隱藏 */ onHide: function () { }, /** * 生命週期函式--監聽頁面解除安裝 */ onUnload: function () { }, /** * 頁面相關事件處理函式--監聽使用者下拉動作 */ onPullDownRefresh: function () { }, /** * 頁面上拉觸底事件的處理函式 */ onReachBottom: function () { }, /** * 使用者點選右上角分享 */ onShareAppMessage: function () { } })message.js
雖然我們吧list引入進來了,下面就是吧這個list顯示出來了
我們用虛擬賬號,給我的主號提交了兩個申請來進行測試了
之後在message.wxml中對我們的資訊進行列印:
<!--miniprogram/pages/message/message.wxml--> <view class="message" wx:if="{{ logged }}"> <view wx:if="{{ !userMessage.length }}"> <text class="message-text">暫無訊息:</text> </view> <view wx:else> <text class="message-text">訊息列表:</text> <view wx:for="{{ userMessage }}" wx:key="{{index}}">{{item}}</view> </view> </view>
我們還要進行優化,就是可以得到一個列表,有頭像有暱稱,等資訊的,別還要有刪除的功能的
為了練習一下元件的功能,雖然這個刪除的功能可以直接在這個檔案裡面寫,但是我們還是吧這個刪除變成一個元件的形式l
新建一個removeList的刪除元件,然後就是找到message的JSON檔案引入這個元件
這個元件其實是可以拖拽的?
在文件-》元件-》檢視容器 movable-area和movable-view相互配合的
demo:
<movable-area> <movable-view x="{{x}}" y="{{y}}" direction="all">text</movable-view> </movable-area>
我們設定的結構和樣式:
<!--components/removeList/removeList.wxml--> <movable-area class="area"> <movable-view class="view">小喵喵</movable-view> </movable-area>
/* components/removeList/removeList.wxss */ .area{width:800rpx; height: 150rpx; margin: 20rpx ; position: relative;background: blue;} .view{width:630rpx; height:100%; background: red;position: absolute;left:150rpx;top:0; line-height: 150rpx;text-indent: 10rpx;}
效果;
但是這個時候還是不能進行拖拽的,其中的direction定義的就是拖拽的方向
添加了這個屬性之後:
<!--components/removeList/removeList.wxml--> <movable-area class="area"> <movable-view direction="horizontal" class="view">小喵喵</movable-view> </movable-area>
就可以進行拖拽了
注意;下面設定的z-Index是在設定級別,z-index大的會覆蓋在小的上面的
<!--components/removeList/removeList.wxml--> <movable-area class="area"> <movable-view direction="horizontal" class="view">小喵喵</movable-view> <image src="" /> <view class="delete">刪除</view> </movable-area>
/* components/removeList/removeList.wxss */ .area{width:800rpx; height: 150rpx; margin: 20rpx ; position: relative;border-bottom: 1px #cdcdcd dashed} .view{width:630rpx; height:100%; position: absolute;left:150rpx;top:0; line-height: 150rpx;text-indent: 10rpx;z-index: 2;} image{ width: 100rpx; height: 100rpx; border-radius: 50%; position: absolute; left: 0; top: 0; z-index: 1; } .delete{ width: 200rpx; height: 150rpx; background: red; color: white; position: absolute; right: 0; top: 0; z-index: 1; }
但是得到的效果是:
會發現不管怎麼拖拉,都擋不住後面的刪除--原因就是class==view這塊沒加背景色,雖然層級夠了
給他在wxss裡面新增一個 background:white即可了
刪除那個文字要居中的話,
.delete{ width: 170rpx; height: 100rpx; background: red; color: white; position: absolute; right: 0; top: 0; z-index: 1; line-height: 100rpx; }
效果圖: