Vue.js实现一个SPA登录页面的过程【推荐】


Posted in Javascript onApril 29, 2017

技术栈

  • vue.js 主框架
  • vuex 状态管理
  • vue-router 路由管理

一般过程

在一般的登录过程中,一种前端方案是:

  1. 检查状态:进入页面时或者路由变化时检查是否有登录状态(保存在cookie或者本地存储的值);
  2. 如果有登录态则查询登录信息(uid,头像等...)并保存起来;如果没有则跳转到登录页;
  3. 在登录页面(或者登录框),校检用户输入信息是否合法;
  4. 校检通过后发送登录请求;校检不成功则反馈给用户;
  5. 登录成功则从后端数据中取出session信息保存登录状态(可能需要跳转);登录不成功则提示用户不成功;
  6. 用户做出注销操作时删除登录状态。

下面我根据列出的步骤一一分析如何做代码实现,所有在代码在https://github.com/doterlin/vue-example-login中,并带有较详细注释帮助理解代码。

在此之前假设登录页面路由为/login,登录后的路由为/user_info。这样只需要在App.vue放好router-view用于存放和渲染这两个路由。

// component/App.vue
<template>
<div class="container" id="app">
 <transition name="fade">
 <keep-alive>
  <router-view></router-view>
 </keep-alive>
 </transition>
</div>
</template>
...

并做好vue-router配置:

// js/app.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../component/Login.vue'
import UserInfo from '../component/UserInfo.vue'
Vue.use(VueRouter);
const router = new VueRouter({
 routes: [{
 path: '/login',
 component: Login
 }, {
 path: '/user_info',
 component: UserInfo
 }]
})
...

检查状态与跳转

在两个时候我们需要检查状态:1.用户打开页面时; 2.路由发生变化时;

首先需要写好一个检查登录态的方法checkLogin:

// js/app.js
...
var app = new Vue({
 data: {},
 el: '#app',
 render: h => h(App),
 router,
 store,
 methods:{
 checkLogin(){
  //检查是否存在session
  //cookie操作方法在源码里有或者参考网上的即可
  if(!this.getCookie('session')){
  //如果没有登录状态则跳转到登录页
  this.$router.push('/login');
  }else{
  //否则跳转到登录后的页面
  this.$router.push('/user_info');
  }
 }
 }
})

为了提升用户体验,当用户打开页面时前端需要检查他是否已经登录,不需要用户再次登录。这个实现很简单,我们在vue实例的created钩子里写好:

// js/app.js
...
var app = new Vue({
 ...
 created() {
 this.checkLogin();
 },
 methods:{
 checkLogin(){
  ...
 }
 }
})

另外,路由发生变化时也需要检查登录,以下情景(路由变化)如果我们不检查登录态可能会发生错误:

  • 用户在进入页面时存在登录状态,但在做操作时正好登录过期了;
  • 用户手动删除了cookie/本地storage并做操作;
  • 用户在未登录的情况下手动输入(或者从收藏夹进入)某个需要登录的路由
  • 用户在已登录的情况下进入登录页路由

这些足够成为我们监听路由的理由,实现的话可以利用vue的watch功能:

// js/app.js
...
var app = new Vue({
 ...
 //监听路由检查登录
 watch:{
 "$route" : 'checkLogin'
 },

 //进入页面时
 created() {
 this.checkLogin();
 },

 methods:{
 checkLogin(){
  ...
 }
 }
})

至此,我们就完成了一般过程中的第1步。接下来实现如何获取用户个人信息。

获取用户信息

在成功登录后,我们一般需要从后端显示用户的一些信息,比如昵称,头像,等级等等...获取的话很简单,发一个http请求从后端拉取;但是一般这些信息会在多的路由用到(比如uid一般都需要在各个后端接口中作为参数带上),所以需要保存到全局状态中(vuex):

// component/App.vue
...
<script>
export default {
 ...
 mounted(){
 //组件开始挂载时获取用户信息
 this.getUserInfo();
 },
 methods: {
 //请求用户的一些信息
 getUserInfo(){
  this.userInfo = {
  nick: 'Doterlin',
  ulevel: 20,
  uid: '10000',
  portrait: 'images/profile.png'
  }

  //获取信息请求
  ts.$http.get(url, {
  //参数
  "params": this.userInfo
  }).then((response) => {
  //Success
  if(response.data.code == 0){
   this.$store.commit('updateUserInfo', this.userInfo); 
  }
  }, (response) => {
  //Error
  });

 }
 }
}
</script>
...

当然我们需要在之前配置好,比如在写在app.js或者单独写成store.js并在app.js引入(推荐):

// js/app.js
// Vuex配置
...
const store = new Vuex.Store({
 state: {
 domain:'http://test.example.com', //保存后台请求的地址,修改时方便(比方说从测试服改成正式服域名)
 userInfo: { //保存用户信息
  nick: null,
  ulevel: null,
  uid: null,
  portrait: null
 }
 },
 mutations: {
 //更新用户信息
 updateUserInfo(state, newUserInfo) {
  state.userInfo = newUserInfo;
 }
 }
})
...

输入校验和发送登录请求

为了防止一些不符合预期的字符和过于频繁的请求传到后台,前端要对用户的输入进行校验和防止重复请求。当然不同网站的合法字符不一样,这里只做为空时不合法的校验:

//component/Login.vue
<template>
<div class="login" id="login">
 ...
 <div class="log-email">
  <input type="text" placeholder="Email" :class="'log-input' + (account==''?' log-input-empty':'')" v-model="account"><input type="password" placeholder="Password" :class="'log-input' + (password==''?' log-input-empty':'')" v-model="password">
  <a href="javascript:;" rel="external nofollow" class="log-btn" @click="login">Login</a>
 </div>
 ...
</div>
</template>
<script>
import Loading from './Loading.vue'
export default {
 name: 'Login',
 data(){
  return {
   isLoging: false,
   account: '',
   password: ''
  }
 },
 components:{
 Loading
 },
 methods:{

  //登录逻辑
  login(){
   if(this.account!='' && this.password!=''){
    this.toLogin();
   }
  }
}
</script>
...

这里的this.toLogin就是登录请求的方法,在post密码到后端时不是直接发送,一般会按照后端定的规则加密后在发送,比如哈希算法,例子进行了的双重哈希加密,引用了js/sha1.min.js,大致实现如下:

...
  //登录请求
  toLogin(){

   //一般要跟后端了解密码的加密规则
   //这里例子用的哈希算法来自./js/sha1.min.js
   let password_sha = hex_sha1(hex_sha1( this.password ));

   //需要想后端发送的登录参数
   let loginParam = {
    account: this.account,
    password_sha
   }

   //设置在登录状态
   this.isLoging = true;

   //请求后端
   this.$http.post( 'example.com/login.php', {
   param: loginParam).then((response) => {
   if(response.data.code == 1){
    //如果登录成功则保存登录状态并设置有效期
    let expireDays = 1000 * 60 * 60 * 24 * 15;
    this.setCookie('session', response.data.session, expireDays);
    //跳转
    this.$router.push('/user_info'); 
   }
   }, (response) => {
   //Error
   });
...

这样就完成了第3,4,5个步骤了。最后一步就是注销。

注销

注销时有的需要请求后端有的不需要,关键的事要删除保存的登录状态:

// component/UserInfo.vue
...
 logout(){
  //删除cookie并跳到登录页
  this.isLogouting = true;
  //请求后端,比如logout.php
  // this.$http.post('eaxmple.com/logout.php')...
  //成功后删除cookie
  this.delCookie('session');

  //重置loding状态
  this.isLogouting = false;

  //跳转到登录页
  this.$router.push('/login/');
 }
...

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
通过Jquery遍历Json的两种数据结构的实现代码
Jan 19 Javascript
Ext JS添加子组件的误区探讨
Jun 28 Javascript
javascript 兼容各个浏览器的事件
Feb 04 Javascript
使用jquery制作弹出框效果
Apr 03 Javascript
js闭包实现按秒计数
Apr 23 Javascript
jQuery.trim() 函数及trim()用法详解
Oct 26 Javascript
jQuery封装的屏幕居中提示信息代码
Jun 08 Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 Javascript
使用layui 渲染table数据表格的实例代码
Aug 19 Javascript
微信小程序 网络通信实现详解
Jul 23 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
Sep 16 Javascript
Vue + ts实现轮播插件的示例
Nov 10 Javascript
Vue.js在使用中的一些注意知识点
Apr 29 #Javascript
jQuery实现按比例缩放图片的方法
Apr 29 #jQuery
Vue开发中整合axios的文件整理
Apr 29 #Javascript
Vue.js教程之axios与网络传输的学习实践
Apr 29 #Javascript
jQuery输入框密码的显示隐藏【代码分享】
Apr 29 #jQuery
jQuery实现多张图片上传预览(不经过后端处理)
Apr 29 #jQuery
jQuery设置图片等比例缩小的方法
Apr 29 #jQuery
You might like
Smarty Foreach 使用说明
2010/03/23 PHP
PHP 输出URL的快捷方式示例代码
2013/09/22 PHP
PHP7之Mongodb API使用详解
2015/12/26 PHP
Android AsyncTack 异步任务实例详解
2016/11/02 PHP
Laravel 队列使用的实现
2019/01/08 PHP
Yii框架函数简单用法分析
2019/09/09 PHP
再次更新!MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类 Ver 1.6)
2007/02/05 Javascript
JavaScript 闭包深入理解(closure)
2009/05/27 Javascript
jQuery getJSON()+.ashx 实现分页(改进版)
2013/03/28 Javascript
JavaScript原生对象之Number对象的属性和方法详解
2015/03/13 Javascript
JavaScript实现99乘法表及隔行变色实例代码
2016/02/24 Javascript
纯JS代码实现气泡效果
2016/05/04 Javascript
node.js插件nodeclipse安装图文教程
2020/10/19 Javascript
Jquery揭秘系列:ajax原生js实现详解(推荐)
2016/06/08 Javascript
Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果
2016/07/07 Javascript
深入探讨Vue.js组件和组件通信
2016/09/12 Javascript
支付宝小程序自定义弹窗dialog插件的实现代码
2018/11/30 Javascript
Vue实现导航栏点击当前标签变色功能
2020/08/19 Javascript
用Python编写分析Python程序性能的工具的教程
2015/04/01 Python
python迭代器与生成器详解
2016/03/10 Python
快速了解Python中的装饰器
2018/01/11 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
香港中原电器网上商店:Chung Yuen
2019/06/26 全球购物
远东集团网络工程师面试题
2014/10/20 面试题
个人自我鉴定怎么写
2013/10/28 职场文书
数控技术专业推荐信
2013/11/01 职场文书
护理学毕业生求职信
2013/11/14 职场文书
多媒体专业自我鉴定
2014/02/28 职场文书
幼儿园优秀班主任事迹材料
2014/05/14 职场文书
幼师个人总结范文
2015/02/28 职场文书
合同补充协议书
2016/03/24 职场文书
(开源)微信小程序+mqtt,esp8266温湿度读取
2021/04/02 Javascript
JavaScript流程控制(循环)
2021/12/06 Javascript
python和Appium的移动端多设备自动化测试框架
2022/04/26 Python
SpringBoot使用AOP实现统计全局接口访问次数详解
2022/06/16 Java/Android