17-vue零基础到实战-注册和登录页面「渡一教育」( 三 )

我们可以看到路由守卫中token是从store里面获取的 , 意味着我们是把token的各种状态存放到store里面 , 并进行获取 , 更新 , 删除等操作 , 这就需要引入vuex状态管理 。
vuex
解释一下为什么一个简单的注册登录单页需要用到vuex:项目中我们各个组件的操作基本都需要获取到token进行验证 , 如果组件A存储了一个token , 组件B要获取这个token就涉及到了组件通信 , 这会非常繁琐 。引入vuex , 不再是组件间的通信 , 而是组件和store的通信 , 简单方便 。
安装
$ cnpm i vuex --S
引入
在main.js引入store , vue实例中也要加入store
//引入storeimport store from './store'然后在需要使用vuex的组件中引入
//store index.jsimport Vuex from 'vuex'Vue.use(Vuex)在src文件夹下面新建 store(文件夹)/index.js
//store index.jsimport Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex);//初始化时用sessionStore.getItem('token'),这样子刷新页面就无需重新登录const state = { token: window.sessionStorage.getItem('token'), username: ''};const mutations = { LOGIN: (state, data) => { //更改token的值 state.token = data; window.sessionStorage.setItem('token', data); }, LOGOUT: (state) => { //登出的时候要清除token state.token = null; window.sessionStorage.removeItem('token'); }, USERNAME: (state, data) => { //把用户名存起来 state.username = data; window.sessionStorage.setItem('username', data); }};const actions = { UserLogin({ commit }, data){ commit('LOGIN', data); }, UserLogout({ commit }){ commit('LOGOUT'); }, UserName({ commit }, data){ commit('USERNAME', data); }};export default new Vuex.Store({ state, mutations, actions});可以看到我们通过actions提交mutation , 进行token的更改、清除以及用户名储存的操作 。
此时启动项目 , 可以看到初步的注册登录界面 , 点击注册或登录按钮可以切换到相应界面 , 并有基础的表单验证 , 登录后会进入helloworld页面 。

17-vue零基础到实战-注册和登录页面「渡一教育」

文章插图
我们写好了基础界面 , 接下来就是要把表单数据发送到后台并进行一系列处理 。现在还没有后端接口没关系 , 我们先写好前端axios请求 。
axios
vue的通讯之前使用 vue-resource  , 有很多坑 。直到vue2.0来临 , 直接抛弃 vue-resource  , 而使用 axios。
用途:
封装ajax , 用来发送请求 , 异步获取数据 。以Promise为基础的HTTP客户端 , 适用于:浏览器和node.js 。
安装
$ cnpm i -S axios
引入
import axios from 'axios'
拦截器
在设置vue-router那部分加入了路由守卫拦截需要登录的路由 , 但这种方式只是简单的前端路由控制 , 并不能真正阻止用户访问需要登录权限的路由 。当token失效了 , 但token依然保存在本地 。这时候你去访问需要登录权限的路由时 , 实际上应该让用户重新登录 。这时候就需要拦截器 interceptors + 后端接口返回的http状态码来判断 。
在src文件夹下面新建axios.js(和App.vue同级)
//axios.jsimport axios from 'axios'import store from './store'import router from './router'//创建axios实例var instance = axios.create({ timeout: 5000, //请求超过5秒即超时返回错误 headers: { 'Content-Type': 'application/json;charset=UTF-8' },});//request拦截器instance.interceptors.request.use( config => { //判断是否存在token , 如果存在的话 , 则每个http header都加上token if (store.state.token) { config.headers.Authorization = `token ${store.state.token}`; } return config; });//respone拦截器instance.interceptors.response.use( response => { return response; }, error => { //默认除了2XX之外的都是错误的 , 就会走这里 if (error.response) { switch (error.response.status) { case 401: router.replace({ //跳转到登录页面 path: 'login', query: { redirect: router.currentRoute.fullPath } // 将跳转的路由path作为参数 , 登录成功后跳转到该路由 }); } } return Promise.reject(error.response); });export default { //用户注册 userRegister(data){ return instance.post('/api/register', data); }, //用户登录 userLogin(data){ return instance.post('/api/login', data);}, //获取用户 getUser(){ return instance.get('/api/user'); }, //删除用户 delUser(data){ return instance.post('/api/delUser', data); }}