小程序开发六:登录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"//(前面注册的时候,我们默认用的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的实现与讲解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容