Vue-Axios的封装---登陆注册---axios(二)

2020年07月05日 阅读数:41
这篇文章主要向大家介绍Vue-Axios的封装---登陆注册---axios(二),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

简单的的登陆与注册

第一种—逻辑数据未分离

注册

  • 使用注册原型的方式的axios方法进行
  • 注:有后台更好
<template>
	<div class="register">
		<h1>注册页面</h1>
		<p>用户名:<input type="text" v-model="userInfo.userid"></p>
		<p>邮箱:<input type="text" v-model="userInfo.email"></p>
		<p>密码:<input type="password" v-model="userInfo.userpwd"></p>
		<button class="btn" @click="register()">注册</button>
	</div>
</template>

<script>
	// 导入qs,序列化字符串对象
	import qs from 'qs';
	export default {
		data() {return {
			userInfo : {
				// 这里的数据保证跟数据接口一致
				userid : '',
				userpwd : '',
				email : ''
			}
		}},
		methods : {
			register() {
				this.$Axios.post(
					"https://www.xxx.com/member/xxxxx.php",
					qs.stringify(this.userInfo),
					{
						// 这里qs使用的stringify方法能够将对象序列化,造成json的形式进行数据获取
						headers : {"content-type": "application/x-www-form-urlencoded"}
					}
				).then( res => {
					console.log(res);
					// 当获取数据的状态码等于1时,至关于获取到了
					if(res.data.status == 1) {
						var flag = window.confirm("肯定注册码");
						if(flag) {
							// 跳转到登陆页面
							this.$router.replace("/login");
						}
					}
				})
			}
		}
	}
</script>

<style>
</style>

登陆

  • 登录的时候使用withCredentials : true;传递cookie
  • 跨域cookie上传(服务器要求请求 localhost:8080)它指示了是否该使用相似cookies,authorization headers(头部受权)
  • 或者TLS客户端证书这一类资格证书来建立一个跨站点访问控制(cross-site Access-Control)请求。
  • 在同一个站点下使用withCredentials属性是无效的。
<template>
	<div class="login">
		<h1>登陆</h1>
		<p>用户名: <input type="text" v-model="user.userid"></p>
		<p>密码: <input type="password" v-model="user.pwd"></p>
		<p><button class="btn" @click="login()">登陆</button></p>
	</div>
</template>

<script>
	import axios from 'axios';
	import qs from 'qs';
	export default{
		data(){
			return {user:{fmdo:"login",dopost:"login",userid:"",pwd:""}}
		},
		methods:{
			login(){
				axios.post(
				"https://www.xxx.com/member/xxxx.php",
				 qs.stringify(this.user),
				 {
					 headers:{"Content-Type":"application/x-www-form-urlencoded"},
					 withCredentials:true,//跨域cookie上传(服务器要求请求 localhost:8080)
					 //,它指示了是否该使用相似cookies,authorization headers(头部受权)
					 // 或者TLS客户端证书这一类资格证书来建立一个跨站点访问控制(cross-site Access-Control)请求。
					 // 在同一个站点下使用withCredentials属性是无效的。
				}
				)
				.then(res=>{
					if(res.data.status == 1 ){
						this.$router.replace("/user");
					}
				})
				.catch(err=>{
					console.log(err);
				})
			}
		}
	}
</script>

<style>
</style>

用户页面获取用户数据信息以及注销

<template>
	<div class="user">
		<div class="info">
			<div class="logined" v-if="userInfo.M_ID">
				<span>{{userInfo.M_UserName}}</span> |
				<span>积分:{{userInfo.M_Scores}}</span> |
				<span @click="loginOut()">注销</span>
			</div>
			<div class="nologin" v-else>
				<router-link to="/login">登陆</router-link>/
				<router-link to="/register">注册</router-link>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		data() {return {
			userInfo : {}
		}},
		created() {
			this.getUser();
		},
		methods : {
			getUser() {
				this.$Axios.get(
					"https://www.xxxx.com/member/xxxx.php",
					{withCredentials : true}
				).then( res => {
					this.userInfo = res.data;
				})
			},
			// 注销的时间
			loginOut() {
				this.$Axios.post(
					"https://www.xxx.com/member/xxxx.php",
					"dopost=exit",
					{withCredentials : true}
					// 
				).then( res => {
					if(res.data.status == 1) {
						this.userInfo = {}
					}
				})
			}
		}
	}
</script>

<style lang="less" scoped="scoped">
	.info {
		display: flex;
		align-items: center;
		padding: 0.3rem;
		height: 1.6rem;
		background-color: orange;
		color: #fff;
		a {
			color: #fff;
		}
	}
</style>

第二种—逻辑数据分离—token

  • 观察上一种的逻辑,发现,代码重复率很高javascript

  • 并且,若是咱们须要改变一下后去数据的接口,怎么办?,难道要一个一个文件,一句一句话去更改码?php

  • 显然在真正的项目中,这是不现实的,因此,咱们须要把数据与逻辑进行分离,css

  • 前端,后端,经过cookie进行数据的联系,使用token进行数据的对比校验html

  • 因此在这时咱们须要对数据获取的axios进行封装前端

封装Axios

为何封装axios?

  • 实现默认配置:baseURL,timeout,headers
  • 请求拦截:header添加(token,user)开启加载提示,请求数据的格式化
  • 响应拦截:关闭加载提示,赞成错误处理,响应数据格式
  • 方法扩展:jsonp等

实现

  • vue-cli中的src文件夹下建立一个utils目录,将封装的axios文件放在其下,命名成request.js
  • 使用的有interceptors拦截器
  • 序列化对象使用的是qs
  • 原理就是Promise
/* 封装axios方法 */
import axios from 'axios';
import qs from 'qs';
// 导入 qs parse 方法把序列化数据转对象  stringify方法 把对象转换为 须要序列化数据 {name:"mumu",age:18} 
// stringify 转序列化数据为 name=mumu&age=18
// parse把 name=mumu&age=18 转成{name:"mumu",age:18} 


const BASEURL =  process.env.NODE_ENV === 'production'?'https://www.xxx.com':'';
console.log(process,process.env)
// 设置基础URL  (动态的根据当前的环境不同,设置不同的baseurl)
// process.env webpack的全局变量环境 产品|开发环境判断 给不一样BASEURL


let request = axios.create({
	baseURL:BASEURL,
	timeout:5000
})
// 建立一个axios实例,设置实例的基础url和 超时时间


//requset.拦截器.请求.使用
request.interceptors.request.use(
	config=>{
		// 配置请求头的token信息,从localStorage中获取token信息,因此咱们能够
		// 在获取到后台数据后,将token信息放到localStorage中
		config.headers.token = localStorage.getItem("token");		
		return config},
	err=>Promise.reject(err)
)
// use 两个回调函数 ,第一个回调函数表明正确 reslove,第个回调函数错误 reject
// Promise.reject  再一次向上一一级抛出一个reject错误你
// 发送请求前个请求头headers 添加 token 头信息
// (每当是axios发起请求时候,先执行use里面回调函数方法,)
// (好比每次发起ajax请求 添加token,添加用户名 到header头信息里面)


//requset.拦截器.响应.使用
request.interceptors.response.use(
	res=>{
		// 写一些业务逻辑  关闭加载提示,301 404 500 等错误响应
		//  res.data.status ==1 ==2 ==3 响应的公共逻辑
		return res;
	},
	err=>Promise.reject(err)
)
// 响应请求拦截
// 拦截器就是再请求前,响应前 作一些额外的公共的的事情  请求前添加loading显示 响应前 移除loading


// request是有方法 也是 对象 对象的属性是能够动态的添加(动态添加了一个方法叫postURL)
request.postURL = function(url,data,option={}){
	return new Promise(function(resolve,reject){
		request({
			url:url,
			method:"POST",
			data:qs.stringify(data),
			...option,
			headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",...option.headers},				
		})
		.then(res=>resolve(res))
		.catch(err=>reject(err))
	})
}
//添加一个 postURL方法,
// 最终返回的 当执行 postURL这个方法是最终返回的Promise对象的实例 
// prosmie对象的实例 有两个结果 .then .catch(异步拿到-等待任意时间获取) 回调函数 成功 
// .then 异步获取到 reslove 返回的数
// .catch 获取到 reject返回的 错误信息


/**
 * jsonp 方法
 * @param {tring}  url  请求的地址
 * @param {Object} option 参数  属性jp和属性callback jp:与后端约定回调函数名 默认值是callback | 属性callback: 回调函数名的值 默认值是jp
 *                             
 * @returns {Promise} 返回一个promise 承诺
 *  
 * */

function jsonp(url, option = {}) {
			var jp = option.jp || "callback"; //默认回调函数参数名
			var callback = option.callback || "jp";//默认回调函数参数值
			return new Promise((resolve, reject) => {
				// 查看url是否有jp 没有还要加上
				if (url.indexOf(jp) == -1) {
					url += "&" + jp + "=" + callback;
				}
				// 获取callback的值
				var p1 = url.indexOf(jp);
				var p2 = url.indexOf("&", p1);
				p2 == -1 ? p2 = url.length : '';	
				//若是查找不到设置p2位url.length;

				callback = url.slice(p1 + jp.length + 1, p2);


				// 动态的建立callback方法
				window[callback] = function (data) {
					document.head.removeChild(script);
					resolve(data)
				}

				// 动态建立script标签
				let script = document.createElement("script");
				script.src = url;
				document.head.append(script);
				// script加载失败
				script.onerror = function (e) {
					document.head.removeChild(script);
					reject(e)
				}


			})
		}
// 在建立的request对象添加jsonp方法
request.jsonp = jsonp;


export default request;
// 导出 request 对象 固然就导出 request.postURL

调用封装完毕的Axios—并在添加所须要的方法

  • src目录下新建一个api文件vue

  • api文件中定义须要在哪个模块使用axios的文件java

  • 好比:咱们须要登陆注册,因此能够定义一个user.js文件,将全部的关于登陆与注册相关的方法放入webpack

  • 具体的代码以下ios


import request from '@/utils/request.js';
// 登陆
function Login(data){
	// 返回,封装的axios中的post方法,传递获取数据的地址,以及调用这个方法是须要传递的数据
	return request.postURL("/member/index_login2.php",data);
}

// 注消
function Exit(){
	return request.postURL("/member/index_login2.php",{dopost:"exit"});
}

// 笑话请求
function GetJok(){
	return request.postURL("/mi/list2.php");
}

// 获取用户信息
function GetUser(){
	return request.get("/member/ajax_login.php")
}

// 导出,将定义的方法导出
export {
	Login,
	Exit,
	GetJok,
	GetUser
};

而后进行使用

  • 使用时,只须要将已经定义的api进行调用就好
import {须要使用的方法的名字} from '地址'

登陆

  • 由于封装axios时,咱们就已经定义了,token是从localStorage中获取的,因此在获取的时候追加
<template>
	<div>
		<h1>登陆页面</h1>
		<p><input type="text" placeholder="用户名" v-model="user.userid"></p>
		<p><input type="password" placeholder="密码" v-model="user.pwd"></p>
		<p><button class="btn" @click="login()">登陆</button></p>
	</div>
	
</template>

<script>
	import {Login} from '@/api/user.js'
	export default {
		data(){
			return {
				user:{fmdo:"login",dopost:"login",userid:"",pwd:""},
				}
		},
		methods:{
			login(){
				Login(this.user)
				.then(res=>{
					// 设置token 在 localstrage
					if(res.data.status==1){
						localStorage.setItem("token",res.data.token);
						if(this.$route.query.redirect){
							this.$router.replace(this.$route.query.redirect);
							// 若是有redirect查询参数 跳转到对应的页面
						}else{
							this.$router.replace("/user");
							// 默认跳转到用户中心
						}
						
					}
				})
				.catch(err=>console.log(err))
			}
		}
	}
</script>

<style>
</style>

首页获取并显示用户信息及注销

  • 退出时删除local Storage
<template>
	<div>
		<h1>我的中心</h1>
		<div>
			<p v-if="user.M_ID">
				{{user.M_LoginID}} | 
				积分:{{user.M_Scores}} | 
				<span @click="exit()">退出</span>
			</p>
			<p v-else>
				<router-link to="/login">登陆</router-link> |
				<router-link to="register">注册</router-link>
			</p>
		</div>
		
	</div>
	
</template>

<script>
	import {GetUser,Exit} from '@/api/user.js';
	// 导入获取用户信息的方法 ,退出的方法
	export default {
		data(){return {user:{}}},
		// 默认用户信息为空
		created(){ this.getUser()},
		// 组件建立完毕获取用户
		methods:{
			getUser(){
				GetUser()
				.then(res=>{
					this.user = res.data;
				})
			},
			// 获取用户信息
			exit(){
				Exit()
				.then(res=>{
					if(res.data.status==1){
						this.user = {};
						localStorage.removeItem("token");
					}
				})
				// 退出
			}
		}
	}
</script>

<style>
</style>

token的使用

<template>
	<div>
		<h1>首页</h1>
		<div v-if="list.length">
			<p v-for="item in list" :key="item.docid">{{item.title}}</p>
		</div>
		</div>
</template>
<script>
	import {GetJok} from '@/api/user.js'
	export default {
		data(){return {list:[]}},
		created(){
			this.getJok();
			
		},
		methods:{
			 getJok(){
				 GetJok()
				 .then(res=>{
					if(res.data.status==1){
						alert(res.data.msg);
						this.$router.push("/login?redirect=/");
						// 若是权限,跳转到登陆页面,给查询参数redirect为/
					}
					// 没有权限
					if(res.data.code==0){
						this.list=res.data.result;
					}
					// 有数据
				 })
			 }
		},
		
	}
</script>