上一節:我們簡單介紹了一下項目的基本模板,這里做一下優化,因為默認的模板是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)
上代碼:
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(),本文只是先簡單地過渡使用,并未對其介紹具體的使用方法,對此大家沒有看太明白,也沒多大的關系;關于數據請求,大家不妨接著往后面的內容看,我會在動態首頁的頁面具體講到此函數方法的使用,到時候大家再回過頭來看這一節,就能很清楚地明白這里的數據請求了(為什么我這里先要提出這個概念了,因為登錄注冊是項目的初始頁面,這塊涉及到了接口的使用,所以就粗略地寫了下)
特別說明:
本文以及后續所有的內容,重點在于為大家分析項目的邏輯實現和講解;至于接口失敗或者錯誤,可能是接口過期失效了,有問題歡迎大家隨時提問,謝謝。