小程序開發六:登錄Login頁面的實現與講解

上一節:我們簡單介紹了一下項目的基本模板,這里做一下優化,因為默認的模板是index,我們理解為login登錄頁面,這樣不太好理解,所以我這邊稍作改動,我們將index的頁面重新命名為login頁面,然后刪掉默認給出的logs頁面,

修改前:


修改前

修改后:


修改后

下面正式講解login頁面的處理邏輯和頁面布局:

首先我們來看源代碼(注釋已寫上)

login.wxml

<view class="container">//設置容器
  <view class="userinfo">//設置容器為“userinfo”的盒子
    <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 獲取頭像昵稱 </button>//綁定”用戶信息“數據,如果沒有獲得用戶的信息,則顯示獲取按鈕,并綁定獲取用戶信息的方法
    <block wx:else>//否則顯示用戶的頭像和昵稱
      <image src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto">//helloword的text
    <text class="user-motto">{{motto}}</text>
  </view>
</view>

login.wxss

頁面上的view的樣式設置,這里不過多介紹

login.js(重點)

Page({
 data: {//設置4個參數
   motto: 'Hello World',//座右銘
   userInfo: {},//用戶信息
   hasUserInfo: false,//是否獲得了用戶信息
   canIUse: wx.canIUse('button.open-type.getUserInfo')//判斷小程序的API,回調,參數,組件等是否在當前版本可用
 },
 //事件處理函數
 onLoad: function () {//頁面的啟動函數
    if (app.globalData.userInfo) {
     this.setData({//綁定數據
       userInfo: app.globalData.userInfo,
       hasUserInfo: true
     })
   } else if (this.data.canIUse){
     // 由于 getUserInfo 是網絡請求,可能會在 Page.onLoad 之后才返回
     // 所以此處加入 callback 以防止這種情況
     app.userInfoReadyCallback = res => {
       this.setData({//綁定數據
         userInfo: res.userInfo,
         hasUserInfo: true
       })
     }
   } else {
     // 在沒有 open-type=getUserInfo 版本的兼容處理
     wx.getUserInfo({
       success: res => {
         app.globalData.userInfo = res.userInfo
         this.setData({//綁定數據
           userInfo: res.userInfo,
           hasUserInfo: true
         })
       }
     })
   }
 },
 getUserInfo: function(e) {//獲取用戶信息之后的回調,配合"bindgetuserinfo"的button使用
   console.log(e)
   app.globalData.userInfo = e.detail.userInfo
   this.setData({//綁定數據
     userInfo: e.detail.userInfo,
     hasUserInfo: true
   })
 }
})

上面所說的數據綁定是這么個流程:

1.在.xml文件中,view(text、image、button等等.....)與.js文件中設置的數據(如上面代碼中的"hasUserInfo")進行捆綁,并隨時監聽此數據的變化,然后做出相應的變化(如上面代碼中的,如果hasUserInfo為flase時,則顯示button;反之則隱藏)

2.在.js文件中,處理業務邏輯,并對設置的數據進行操作和賦值,同時刷新綁定數據的view(如在獲取到用戶信息的時候,"hasUserInfo"變為true,這時候在.wxml中綁定的button則進行隱藏,不再顯示)

.wxml進行負責顯示的樣式

.js處理顯示的內容

顯示圖

業務邏輯的分析與實現

業務場景:

1.用戶首次進入小程序,發起注冊請求,注冊完成之后,進行登錄,登錄成功之后,進入動態首頁

2.用戶再次進入程序,已成功檢測用戶注冊過,直接進行登錄,進入動態首頁


那么開始編寫邏輯吧

首先我們.xml中編寫一個登錄的按鈕,并且綁定一個”userLogin“的函數

<button class="loginBtn" catchtap="userLogin">登錄</button>

在點擊了按鈕之后,執行js文件中的userLogin函數

 userLogin: function() {
    //先注冊用戶 然后登陸
    var userInfoData = wx.getStorageSync('userInfoData');//讀取本地是否存在用戶信息(首次進入小程序的情況,肯定不存在用戶信息;只有在用戶注冊并且登錄的情況下,才會去保存本地用戶信息)
    if (!userInfoData) {
      console.log('用戶沒有注冊登錄過');
      this.registerAccount();//注冊用戶
    } else {
      console.log('用戶注冊登錄過');
      this.loginAccount(userInfoData.username);//登錄(為什么本地有了用戶信息卻還要登錄呢,一般來說,這里的登錄是為了方便刷新用戶資料信息,便于同步)
    }
  }

思路詳解:
首先我們讀本是否有本地的用戶數據,不存在,則進行注冊然后登錄;存在的話,重新登錄,便于刷新用戶數據。

重點來看注冊的registerAccount()函數和登錄的loginAccount()函數;

registerAccount()

      /*注:
這里因為我調的接口是來自移動端的接口設計(強調),所以我這邊傳的三個參數為:
username(用戶名)
nick_nam(注冊用戶的昵稱)
password(注冊用戶的密碼)

正確的小程序的注冊參數一般為:
js_code( wx.login登錄時獲取的 code,用于后續獲取session_key)
encryptedData ( 包括敏感數據在內的完整用戶信息的加密數據)
iv( 加密算法的初始向量)
      */
  registerAccount: function() {
    var that = this;
    var paraData = {
      username: "TEST002",//(切記,真正的這里的傳參要使用唯一的標志符號)
      nick_name: this.data.userInfo.nickName,
      password: "111111"(因為我們是直接微信授權)
    }
    var cookie = wx.getStorageSync('cookie');
    if (cookie) { //保險起見 先移除掉
      wx.removeStorageSync('cookie');
    }
    requestTool.postRequest("/user/register", paraData, that.registerGetSuccess, that.registerGetFailed);
  },
  //注冊成功的回調
  registerGetSuccess: function(data) {
    console.log("注冊成功");
    var userName = data.username;
    this.loginAccount(userName);
  },
  //注冊失敗的回調
  registerGetFailed: function(res) {
    console.log("注冊失敗" + res);
  },

loginAccount()

  loginAccount: function(userName) {
    var that = this;
    var paraData = {
      username: userName,//注冊時使用的用戶名
      password: "111111"http://(前面注冊的時候,我們默認用的111111的密碼)
    }
    var cookie = wx.getStorageSync('cookie');
    if (cookie) { //保險起見 先移除掉
      wx.removeStorageSync('cookie');
    }
    requestTool.postRequest("/user/login", paraData, that.loginGetSuccess, that.loginGetFailed);

  },

  loginGetSuccess: function(data) {
    console.log("登錄成功" + data);
    //填充數據
    var userInfoData = {};
    userInfoData["id"] = data._id;
    userInfoData["username"] = data.username;
    userInfoData["nick_name"] = data.nick_name;
    userInfoData["age"] = data.age;
    userInfoData["sex"] = data.sex;
    userInfoData["avatar"] = this.data.userInfo.avatarUrl;//因為后臺會返回一個默認的頭像地址,這里我們將微信的頭像地址替換此數據。
    //向緩存中存入數據“ userInfoData”
    wx.setStorageSync('userInfoData', userInfoData);

    //去到動態主頁面首頁(tab頁面)
    //注意:凡是去到tab頁面,千萬不能用wx.navigateTo 或者 wx.redirectTo,要使用wx.switchTab或者wx.lanchTo
    wx.switchTab({
      url: '../home/home',
    })
  },

  loginGetFailed: function(res) {
    console.log("登錄失敗" + res);
  },

補充:

上述的網絡請求,已經封裝到utils文件夾中
(另外的幾個文件后面的開發中會一個個提到,這次只講request.js)


request.js

上代碼:

var app = getApp();
//項目URL相同部分,減輕代碼量,同時方便項目遷移
//這里因為我是本地調試,所以host不規范,實際上應該是你備案的域名信息

/**
 * POST請求,
 * URL:接口
 * postData:參數,json類型
 * doSuccess:成功的回調函數
 * doFail:失敗的回調函數
 */
function postRequest(urlPath, postData, doSuccess, doFail) {
  var requestUrl = app.globalData.mianServerUrl + urlPath;
  var header = {};
  header["content-type"] =  "json";
  header["meme-app"] = "CCC";
  var cookie = wx.getStorageSync('cookie');
  if(cookie){
    header["cookie"] = cookie;
  }
  wx.request({
    //項目的真正接口,通過字符串拼接方式實現
    url: requestUrl,
    header: header,
    data: postData,
    method: 'POST',
    success: function (res) {
      //參數值為res.data,直接將返回的數據傳入
      if (urlPath == '/user/login'){//存cookie
        var cookie = res.header.Cookie;
        if(!cookie){
          cookie = res.header.cookie;
        }
        wx.setStorageSync('cookie', cookie);
        console.log(res.header + '獲得的頭部s');
      }
      doSuccess(res.data);
    },
    fail: function (res) {
      doFail(res);
    },
    
  })
}

/**
 * GET請求,
 * urlPath:接口
 * paraData
 * doSuccess:成功的回調函數
 * doFail:失敗的回調函數
 */
function getRequest(urlPath,paraData, doSuccess, doFail) {
  
  var requestUrl = app.globalData.mianServerUrl + urlPath;
  var header = {};
  header["content-type"] = "json";
  header["meme-app"] = "CCC";
  var cookie = wx.getStorageSync('cookie');
  if (cookie) {
    header["cookie"] = cookie;
  }
  wx.request({
    url: requestUrl,
    data: paraData,
    header: header,
    method: 'GET',
    success: function (res) {
      doSuccess(res.data);
    },
    fail: function (res) {
      console.log(res);
      doFail();
    },
  })
}

/**
 * module.exports用來導出代碼
 * js文件中通過var call = require("../util/request.js")  加載
 * 在引入引入文件的時候"  "里面的內容通過../../../這種類型,小程序的編譯器會自動提示,因為你可能
 * 項目目錄不止一級,不同的js文件對應的工具類的位置不一樣
 */

module.exports = {
  postRequest: postRequest,
  getRequest: getRequest
}

注:
文件中的
var requestUrl = app.globalData.mianServerUrl + urlPath;
需要在app.js文件中定義:

 globalData: {
     mianServerUrl: "https://api.ytqig.cn"
  }

在需要用到此封裝的request.js時候,都需要進行引入
我在login.js文件中也引入了

var requestTool = require("../../utils/request.js");

當用戶注冊并且登錄成功之后,進進入了home頁面了

 wx.switchTab({//進入首頁
      url: '../home/home',
    })

注意:一旦有頁面的顯示,必須要在app.json中進行插入和申明:

 "pages": [
    "pages/login/login",
    "pages/home/home"
  ],

好了,我們來編譯下項目,并且來分析一下我們的數據存儲過程吧;

1.首先我們是第一次進入小程序,我們先進行授權,授權成功之后,獲得到微信的頭像和昵稱,用于注冊時候的傳參;
2.點擊登錄按鈕,執行registerAccount()函數;
3.注冊成功后,執行loginAccount()
4.登錄成功之后,執行wx.swtichTab,進入home頁面

補充說明:

上述講到的數據請求wx.request(),本文只是先簡單地過渡使用,并未對其介紹具體的使用方法,對此大家沒有看太明白,也沒多大的關系;關于數據請求,大家不妨接著往后面的內容看,我會在動態首頁的頁面具體講到此函數方法的使用,到時候大家再回過頭來看這一節,就能很清楚地明白這里的數據請求了(為什么我這里先要提出這個概念了,因為登錄注冊是項目的初始頁面,這塊涉及到了接口的使用,所以就粗略地寫了下)

特別說明:

本文以及后續所有的內容,重點在于為大家分析項目的邏輯實現和講解;至于接口失敗或者錯誤,可能是接口過期失效了,有問題歡迎大家隨時提問,謝謝。

完結:

傳送門:
七:動態首頁Home的實現與講解

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容