1. 程式人生 > >Day10-微信小程式實戰-交友小程式-新增好友功能之建立並更新message資訊

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;
}

效果圖: