封装一个axios请求工具
封装好的请求工具request.js
// 在此封装好 前端发送 http请求的工具
// (目的:一切都是为了代码复用与简化,程序员的偷懒毛病,不过这也是一个好的出发点,也是人类的通病)
import axios from 'axios';
import router from "@/router";
// 创建一个新的axios对象
const request = axios.create({
baseURL: process.env.VUE_APP_BASEURL, // 后端的接口地址 ip:port
timeout: 30000 // 30s后请求将超时
})
// request 请求拦截器
// 可以自请求发送前 对请求做一些处理
// 比如统一加token,对请求参数 统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8'; // 设置请求头格式
let user = JSON.parse(localStorage.getItem("xm-user") || '{}') // 获取缓存的用户信息
config.headers['token'] = user.token // 设置请求头
// 返回请求进行发送
return config
}, error => {
console.error('request error: ' + error) // for debug
return Promise.reject(error)
});
// response 响应拦截器
// 可以 在接口响应后 统一处理结果
request.interceptors.response.use(
response => {
// 进行第一层解析 后续的简化操作
let res = response.data;
// 兼容服务端返回的字符串数据 本项目可以不需要此判断
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
// 如果响应码为401则进行跳转 返回登录页面
if (res.code === '401') {
// 页面跳转 跳转到登录页面
router.push('/login')
}
// 返回后端的响应继续给前端(浏览器)进行渲染
return res;
},
error => {
console.error('response error: ' + error) // for debug
return Promise.reject(error)
}
)
// 默认导出 对外暴露出来
export default request
在Vue.js2中的使用步骤
首先进行全局注册(在main.js中)
// 引入或注册
import request from "@/utils/request";
// 使得请求 成为 全局请求属性$request 后续直接用$request即可
// 或者称为 注册成Vue应用的全局属性 也是为了更加方便调用
Vue.prototype.$request = request
Vue.prototype.$baseUrl = process.env.VUE_APP_BASEURL
在Vue组件中进行调用
如下,进行组件中使用的举例(Admin.vue组件) 只看下面的js部分代码即可
<!-- 管理员页面 -->
<template>
<div>
<div class="search">
<el-input placeholder="请输入账号查询" style="width: 200px" v-model="username"></el-input>
<el-button type="info" plain style="margin-left: 10px" @click="load(1)" icon="el-icon-search">查询</el-button>
<el-button type="warning" plain style="margin-left: 10px" @click="reset">重置 <i class="el-icon-refresh"></i> </el-button>
</div>
<div class="operation">
<el-button type="primary" plain @click="handleAdd">新增 <i class="el-icon-edit-outline"></i> </el-button>
<el-button type="danger" plain @click="delBatch"> <i class="el-icon-warning"></i> 批量删除</el-button>
</div>
<!-- 表格数据 -->
<div class="table">
<el-table append="solt" :data="tableData" strip
@selection-change="handleSelectionChange" border stripe>
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column prop="id" label="序号" width="70" align="center" sortable></el-table-column>
<el-table-column prop="username" label="账号" align="center"></el-table-column>
<el-table-column prop="name" label="姓名" align="center">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>电话: {{ scope.row.phone }}</p>
<p>邮箱: {{ scope.row.email }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" align="center"></el-table-column>
<el-table-column prop="email" label="邮箱" align="center"></el-table-column>
<!-- -->
<el-table-column label="头像">
<template v-slot="scope">
<div style="display: flex; align-items: center">
<el-image style="width: 40px; height: 40px; border-radius: 50%" v-if = "scope.row.avatar != null"
:src="isNull(scope)" :preview-src-list="[scope.row.avatar]">
</el-image>
<el-image style="width: 40px; height: 40px; border-radius: 50%" v-else = "scope.row.avatar === null"
:src="url" :preview-src-list="[url]">
</el-image>
</div>
</template>
</el-table-column>
<el-table-column prop="role" label="角色"></el-table-column>
<el-table-column label="操作" align="center" width="180">
<template v-slot="scope">
<el-button size="mini" type="primary" plain @click="handleEdit(scope.row)" icon="el-icon-edit">编辑</el-button>
<el-button size="mini" type="danger" plain @click="del(scope.row.id)" icon="el-icon-delete">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- -->
<div class="pagination">
<el-switch v-model="value">
</el-switch>
<el-pagination
:hide-on-single-page="value"
background
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[pages, pages + 5, pages + 10]"
:page-size="pageSize"
layout="total, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</div>
<!-- 弹窗数据 -->
<el-dialog title="管理员" :visible.sync="fromVisible" width="40%" :close-on-click-modal="false" destroy-on-close>
<el-form :model="form" label-width="100px" style="padding-right: 50px" :rules="rules" ref="formRef">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="用户名"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone" placeholder="电话"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="邮箱"></el-input>
</el-form-item>
<el-form-item label="头像">
<el-upload
class="avatar-uploader"
:action="$baseUrl + '/files/upload'"
:headers="{ token: user.token }"
list-type="picture"
:on-success="handleAvatarSuccess"
>
<el-button type="primary"><i class="el-icon-s-custom"></i> 更新头像</el-button>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="save">确 定</el-button>
<el-button @click="fromVisible = false" type="info">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
// 对外暴露
export default {
name: "Admin",
data() {
return {
pages: 5,
scope:'',
value: false,
url: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', // 默认头像 网络图片
tableData: [], // 所有的数据
pageNum: 1, // 当前的页码
pageSize: 2, // 每页显示的个数
total: 0,
username: null,
fromVisible: false,
form: {},
user: JSON.parse(localStorage.getItem('xie12') || '{}'),
rules: {
username: [
{required: true, message: '请输入账号', trigger: 'blur'},
]
},
ids: []
}
},
created() {
this.load(1)
},
methods: {
// 头像默认 可废弃方法 直接用 scope.row.avatar 替换
isNull(scope) {
if(scope.row.avatar === null) {
scope.row.avatar = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png' // 默认头像 网络图片
} else {
scope.row.avatar = scope.row.avatar
}
return scope.row.avatar
},
handleAdd() { // 新增数据
this.form = {} // 新增数据的时候清空数据
this.fromVisible = true // 打开弹窗
},
handleEdit(row) { // 编辑数据
this.form = JSON.parse(JSON.stringify(row)) // 给form对象赋值 注意要深拷贝数据
this.fromVisible = true // 打开弹窗
},
save() { // 保存按钮触发的逻辑 它会触发新增或者更新
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$request({
url: this.form.id ? '/admin/update' : '/admin/add',
method: this.form.id ? 'PUT' : 'POST',
data: this.form
}).then(res => {
if (res.code === '200') { // 表示成功保存
this.$message.success('保存成功')
// 分页查询展示,展示第一页
this.load(1)
this.fromVisible = false
} else {
this.$message.error(res.msg) // 弹出错误的信息
}
})
}
})
},
del(id) { // 单个删除
this.$confirm('您确定删除吗?', '确认删除', {type: "warning"}).then(response => {
this.$request.delete('/admin/delete/' + id).then(res => {
if (res.code === '200') { // 表示操作成功
this.$message.success('操作成功')
this.load(1)
} else {
this.$message.error(res.msg) // 弹出错误的信息
}
})
}).catch(() => {
})
},
handleSelectionChange(rows) { // 当前选中的所有的行数据
this.ids = rows.map(v => v.id)
},
delBatch() { // 批量删除
if (!this.ids.length) {
this.$message.warning('请选择数据')
return
}
this.$confirm('您确定批量删除这些数据吗?', '确认删除', {type: "warning"}).then(response => {
this.$request.delete('/admin/delete/batch', {data: this.ids}).then(res => {
if (res.code === '200') { // 表示操作成功
this.$message.success('操作成功')
this.load(1)
} else {
this.$message.error(res.msg) // 弹出错误的信息
}
})
}).catch(() => {
})
},
load(pageNum) { // 分页查询
if (pageNum) this.pageNum = pageNum
this.$request.get('/admin/selectPage', {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
username: this.username,
}
}).then(res => {
this.tableData = res.data?.list
this.total = res.data?.total
})
},
reset() {
this.username = null
this.load(1)
},
handleCurrentChange(pageNum) {
this.load(pageNum)
},
handleAvatarSuccess(response, file, fileList) {
// 把头像属性换成上传的图片的链接
this.form.avatar = response.data
},
}
}
</script>
<!-- 样式 -->
<style scoped>
</style>