上一节:我们简单介绍了一下项目的基本模板,这里做一下优化,因为默认的模板是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"//(前面注册的时候,我们默认用的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(),本文只是先简单地过渡使用,并未对其介绍具体的使用方法,对此大家没有看太明白,也没多大的关系;关于数据请求,大家不妨接着往后面的内容看,我会在动态首页的页面具体讲到此函数方法的使用,到时候大家再回过头来看这一节,就能很清楚地明白这里的数据请求了(为什么我这里先要提出这个概念了,因为登录注册是项目的初始页面,这块涉及到了接口的使用,所以就粗略地写了下)
特别说明:
本文以及后续所有的内容,重点在于为大家分析项目的逻辑实现和讲解;至于接口失败或者错误,可能是接口过期失效了,有问题欢迎大家随时提问,谢谢。