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 相关文章推荐
9行javascript代码获取QQ群成员具体实现
Oct 16 Javascript
js中数组(Array)的排序(sort)注意事项说明
Jan 24 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
Sep 07 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
Aug 25 Javascript
微信小程序 实现拖拽事件监听实例详解
Nov 16 Javascript
JavaScript中捕获与冒泡详解及实例
Feb 03 Javascript
在js代码拼接dom对象到页面上去的模板总结(必看)
Feb 14 Javascript
js学习心得_一个简单的动画库封装tween.js
Jul 14 Javascript
jquery 实现拖动文件上传加载进度条功能
Mar 18 jQuery
LayerClose弹窗关闭刷新方法
Aug 17 Javascript
对vuex中getters计算过滤操作详解
Nov 06 Javascript
JavaScript遍历数组的方法代码实例
Jan 14 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
3种平台下安装php4经验点滴
2006/10/09 PHP
php intval的测试代码发现问题
2008/07/27 PHP
php目录管理函数小结
2008/09/10 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
php限制上传文件类型并保存上传文件的方法
2015/03/13 PHP
Smarty中的注释和截断功能介绍
2015/04/09 PHP
PHP使用内置函数生成图片的方法详解
2016/05/09 PHP
Apache无法自动跳转却显示目录的解决方法
2020/11/30 PHP
Yii2针对指定url的生成及图片等的引入方法小结
2016/07/18 PHP
Json_decode 解析json字符串为NULL的解决方法(必看)
2017/02/17 PHP
浅谈ThinkPHP中initialize和construct的区别
2017/04/01 PHP
Prototype PeriodicalExecuter对象 学习
2009/07/19 Javascript
ExtJS 入门
2010/10/29 Javascript
分享20款美化网站的 jQuery Lightbox 灯箱插件
2014/10/10 Javascript
js实现刷新iframe的方法汇总
2015/04/27 Javascript
checkbox批量选中,获取选中项的值的简单实例
2016/06/28 Javascript
jquery 动态增加,减少input表单的简单方法(必看)
2016/10/12 Javascript
Validform表单验证总结篇
2016/10/31 Javascript
JS前端加密算法示例
2016/12/22 Javascript
js实现rem自动匹配计算font-size的示例
2017/11/18 Javascript
Vue 动态设置路由参数的案例分析
2018/04/24 Javascript
js数组去重的N种方法(小结)
2018/06/07 Javascript
vue-auto-focus: 控制自动聚焦行为的 vue 指令方法
2018/08/25 Javascript
vue debug 二种方法
2018/09/16 Javascript
Vue高版本中一些新特性的使用详解
2018/09/25 Javascript
ng-alain的sf如何自定义部件的流程
2020/06/12 Javascript
微信小程序仿抖音短视频切换效果的实例代码
2020/06/24 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
2021/02/08 Javascript
Python实现的一个简单LRU cache
2014/09/26 Python
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
浅谈Django的缓存机制
2018/08/23 Python
python matplotlib imshow热图坐标替换/映射实例
2020/03/14 Python
Craghoppers德国官网:户外和旅行服装
2020/02/14 全球购物
高中生操行评语大全
2014/04/25 职场文书
客房服务员岗位职责
2015/02/09 职场文书
趣味运动会口号
2015/12/24 职场文书