记得配置完vue.confing.js要重启项目
前提是你全部搭建了项目,现在开始写代码了。没有下载的没了要下载啊
可以npm i axios 或者yarn add axios 等
上图
这里是我的package.json文件,用什么自己下载什么。
一定要记得,你下载了什么就在mian.js 里引入什么
代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
import echarts from "echarts";
import axios from 'axios'
import api from './request/http/api' // 导入api接口// 导入api接口 这个是后来写的,直接引过来了,代码在下边。
Vue.prototype.$api = api; // 将api挂载到vue的原型上
Vue.prototype.$echarts = echarts;
Vue.prototype.$axios = axios;
Vue.config.productionTip = false
Vue.use(Antd);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
好了,此时就可以写axios 的封装和 vue.config.js代理了
上图
代码你可以直接拿走,把后边的改了就行
module.exports = {
devServer: {
port: 8000, // 端口号
proxy: { // 代理
[process.env.NODE_ENV]: {
target: "http://iot-dev.com", // 接口的域名,也就是需要跨域的目标url ,我这里是项目用到的
changeOrigin: true, // 开启代理,将基于名称的虚拟托管网站的选项,如果不配置,请求会报404
ws: true,
pathRewrite: { // 重写地址
"^/api": "" // 若请求的路径在目标url下,但不在/api 下,则将其转换成空
}
},
// 第二个代理
"/api": {
target: "http://iot-dev..com", // 接口的域名,也就是需要跨域的目标url ,我这里是项目用到的
changeOrigin: true, // 开启代理,将基于名称的虚拟托管网站的选项,如果不配置,请求会报404
ws: true,
pathRewrite: { // 重写地址
"^/api": "" // 若请求的路径在目标url下,但不在/api 下,则将其转换成空
}
}
},
},
}
然后是写静态页面,假设我们已经创建了一个登录页面,此时要根据接口存token 并且在后续用token。
在template里写代码 上图
上代码 ,样式自己写吧,我也有点懒
div
<input type="text" v-model="loginForm.username" placeholder="用户名"/
<input type="text" v-model="loginForm.password" placeholder="密码"/
<button @click="login">登录</button>
div
import { mapMutations} from 'vuex'
export default {
name: "Home",
components: {},
data(){
return {
loginForm: {
username:'',
password:'',
},
}
},
methods: {
...mapMutations(['changeLogin']),
login() {
let _this = this
if (this.loginForm.username === '' || this.loginForm.password === '') {
alert ('账号密码不能为空')
} else {
this.axios({
method: 'post',
url: '/user/login',
data: _this.loginForm
}).then(res => {
console.log(res.data)
_this.userToken = "Bearer" + res.data.data.body.token
// 将用户token保存到vuex 里
_this.changeLogin({Authorization: _this.userToken})
_this.$router.push('/about')
alert('登录成功')
}).catch(err => {
alert('账号或密码错误')
console.log(err)
})
}
},}
这个是页面的简单逻辑。这里我们token用到了vuex。所以我们在store仓库里就要用到 在store下的index.js文件里写,你也可以单独拿出去写,但是记得要导出结合引入
上图 store
上代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 存token
Authorization: localStorage.getItem('token') ? localStorage.getItem('token') : ''
},
mutations: {
// 修改token,并将token存入localStorage
changeLogin(state, user) {
state.Authorization = user.Authorization;
localStorage.setItem('token', user.Authorization);
},
}
好了这个时候我们要记得在跟路由router下的index.js 里搞搞
上代码
import Vue from ‘vue’
import VueRouter from ‘vue-router’
import login from '…/views/login.vue’
Vue.use(VueRouter)
const routes = [
这里应该在写一个重定向的路由,自己写吧。看你们定哪里就写那个路由吧。
{
path: '/',
name: 'login',
component: login
},]
const router = new VueRouter({
routes
})
// 导航守卫
// 使用router.beforeEach 注册全局前置守卫,判断用户是否登录
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next()
} else {
let token = localStorage.getItem('token')
if (!token || token === '' || token === 'null') {
next('/login')
} else {
next()
}
}
})
export default router
弄到了这里也就差不多了,剩下的就是封装axios了。这里我觉的写的比较全了,您要是有建议可以沟通一下啊,我也比较小白。
一、axios的封装
在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,
它是基于promise的http库,可运行在浏览器端和node.js中。
他可以拦截请求和响应、取消请求、转换json、客户端防御XSRF等。
安装
npm install axios; // 安装axios
引入
一般我会在项目的src目录中,新建一个request文件夹,
然后在里面新建一个http文件夹创建index.js和一个api.js文件。
http文件夹下的index.js 用来封装我们的axios,api.js用来统一管理我们的接口。
http-===index.js文件内容:
// http.js文件下的index.js用来封装我们的axios的
import { message } from 'ant-design-vue';
import axios from 'axios'; // 引入axios
import QS from 'qs'; // 引入qs模块,用来序列化post类型的数据,后面会提到
import { Toast } from 'vant'; // vant 里的轻提示组件
import router from '../../router'; // 根路径地址
import store from '@/store/index'; // 引入vuex里的文件库
// 允许跨域携带cookie信息是登录请求预处理,没有此设置,后端就无法讲数据保存到cookie中
// axios.defaults.withCredentials = true 这个一般写在mian.js 中,但是注意会报错
// 解决:在这里我们只需要改成(后端改的) response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8080前端地址"
// axios.defaults.baseURL //可以设置axios的默认请求地址
// 环境的切换 process.env.NODE_ENV是vue.config.js的文件夹下proxy的代理名称
if (process.env.NODE_ENV == 'development') { // 开发环境
axios.defaults.baseURL = '/api1'
} else if (process.env.NODE_ENV == 'debug') { // 测试环境
axios.defaults.baseURL = '/api2'
} else if (process.env.NODE_ENV == 'production') { // 生产环境
axios.defaults.baseURL = '/api3'
}
axios.defaults.timeout = 10000; // 设置请求超时
// 请求头
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
// axios.defaults.headers = { // 创建 axios 实例
// 'Content-Type': 'application/json'
// };
// 请求拦截=====请求前的处理//axios设置请求拦截器
axios.interceptors.request.use(config => {
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,
// 不用每次请求都手动添加了 即使本地存在token,也有可能token是过期的,
// 所以在响应拦截器中要对返回状态进行判断
const token = store.state.token
// const token = localStorage.getItem('token')
// if(token && (config.headers.Authorization = token)){}
token && (config.headers.Authorization = token) // Authorization令牌
if ((config.method === 'get' || config.method === 'delete') && config.data) {
config.url += '?' + objToStr(config.data || {})
} else if (config.method === 'deleteall') { // 全部删除
config.method = 'delete'
} else if (config.method === 'upload') { // 上传
config.method = 'post'
config.headers = {'Content-Type' : 'application/x-www-form-urlencoded'} //设置响应头
}
if (config.api) {
config.url = config.api +config.url
} else {
config.url = "/api/platform_device" + config.url
}
console.log(axios.defaults)
return config
}, err => {
if (err.response) {
const data = err.response.data
data.message && message.err(data.message)
}
console.log(err)
return Promise.error(err)
})
function objToStr(obj) {
if (obj && typeof obj === 'object') {
let urlQuery = ''
for (const name in obj) {
urlQuery += name + '=' + obj[name] + '&'
}
return urlQuery.slice(0, urlQuery.length - 1)
} else {
return ''
}
}
// 响应的拦截
// 响应拦截器=====请求后的处理
axios.interceptors.response.use((res) => {
if (res.status === 200 && res.data) {
if (res.data.status === 200 && res.data.rel) {
return Promise.resolve(res.data)
} else {
res.data.message && message.error(res.data.message)
return Promise.reject(res.data)
}
}
return Promise.reject(res.data)
}, error => { // 服务器状态码不是200的情况
if (error.response.status) {
switch (error.response.status) {
case 401: // 未登录
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
case 403: // token过期
Toast({
message: '登录过期,请重新登录',
duration: 1000, // 时长
forbidClick: true // 不允许点击
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将浏览器的页面fullPath传过去
// 登录成功之后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
})
}, 1000);
break;
case 404: // 请求不存在
Toast({
message: '网络请求不存在',
duration: 1500,
forbidClick: true
})
break;
default: // 其他的错误
Toast({
message: error.response.data.message,
duration: 1500,
forbidClick: true
})
}
return Promise.reject(error.response)
}
})
export {
axios, QS
}
好了,剩下的就是封装api接口了*
api.js 文件**
// api.js用来统一管理我们的接口
import { axios, QS} from './index' //引入qs模块,用来序列化post类型的数据
// 获取设备列表-分页
export function facilityPageList(params) {
return axios({
url: '/device/myEquipment/queryMyEquipmentPage',
method: 'post',
data: params
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// }
})
}
// 或者写成下边的样子
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
axios.get(url, {
params: params
})
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, QS.stringify(params))
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
可以直接拿走用。