(十一).netcore+vue axios实现页面功能
本章目的:调用API实现页面功能
一、安装axios
npm install --save axios
二、封装axios调用方法
js/api.js
import axios from 'axios'; import Vue from 'vue'; let base = 'http://localhost:8022'; axios.defaults.timeout = 20000 // 自定义判断元素类型JS function toType(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() } // 参数过滤函数 function filterNull(o) { for (var key in o) { if (o[key] === null) { delete o[key] } if (toType(o[key]) === 'string') { o[key] = o[key].trim() } else if (toType(o[key]) === 'object') { o[key] = filterNull(o[key]) } else if (toType(o[key]) === 'array') { o[key] = filterNull(o[key]) } } return o } axios.interceptors.request.use( config => { return config }, err => { return Promise.reject(err); } ); // http response 拦截器 axios.interceptors.response.use( response => { return response; }, error => { // 超时请求处理 var originalRequest = error.config; if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1 && !originalRequest._retry) { Vue.prototype.$message({ message: '请求超时!', type: 'error' }); originalRequest._retry = true return null; } if (error.response) { if (error.response.status == 401) { //需要授权 } // 403 无权限 if (error.response.status == 403) { Vue.prototype.$message({ message: '失败!该操作无权限', type: 'error' }); return null; } // 429 ip限流 if (error.response.status == 429) { Vue.prototype.$message({ message: '刷新次数过多,请稍事休息重试!', type: 'error' }); return null; } } return ""; // 返回接口返回的错误信息 } ); // 角色管理 export const getRoleListPage = params => { return axios.get(`${base}/api/role/get`, { params: params }); }; export const removeRole = params => { return axios.delete(`${base}/api/role/delete`, { params: params }); }; export const editRole = params => { return axios.put(`${base}/api/role/put`, params); }; export const addRole = params => { return axios.post(`${base}/api/role/post`, params ); };
三、页面代码
角色页面 views/User/Roles.vue
<template>
<section>
<!--工具条-->
<el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
<el-form :inline="true" @submit.native.prevent>
<el-form-item>
<el-input v-model="filters.name" placeholder="请输入内容"></el-input>
</el-form-item>
<el-button type="primary" @click="getRoles">查询</el-button>
<el-button type="primary" @click="handleAdd">新增</el-button>
<el-button type="primary" @click="handleEdit">修改</el-button>
<el-button type="danger" @click="handleDel">删除</el-button>
</el-form>
</el-col>
<!--列表-->
<el-table :data="datalist"
highlight-current-row
v-loading="listLoading"
@current-change="selectCurrentRow"
style="width: 100%;">
<el-table-column type="index" width="80"></el-table-column>
<el-table-column prop="RoleName" label="角色名" width sortable></el-table-column>
<el-table-column prop="Description" label="说明" width sortable></el-table-column>
<el-table-column prop="CreateTime" label="创建时间" :formatter="formatCreateTime" width sortable></el-table-column>
<el-table-column prop="Enabled" label="状态" width="200" sortable>
<template slot-scope="scope">
<el-tag :type="scope.row.Enabled ? 'success' : 'danger'"
disable-transitions>{{scope.row.Enabled ? "正常":"禁用"}}</el-tag>
</template>
</el-table-column>
</el-table>
<VuePagination ref="vuePagination"
:current-page="pagination.currentPage"
:pageSize="pagination.pageSize"
:totals="pagination.totals"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
<!--编辑界面-->
<el-dialog title="编辑"
:visible.sync="editFormVisible"
v-model="editFormVisible"
:close-on-click-modal="false">
<el-form :model="editForm" label-width="80px" :rules="editFormRules" ref="editForm">
<el-form-item label="角色名" prop="RoleName">
<el-input v-model="editForm.RoleName" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="状态" prop="Enabled">
<el-select v-model="editForm.Enabled" placeholder="请选择角色状态">
<el-option v-for="item in statusList"
:key="item.value"
:label="item.name"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="说明" prop="Description">
<el-input v-model="editForm.Description" auto-complete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="editFormVisible = false">取消</el-button>
<el-button type="primary" @click.native="editSubmit" :loading="editLoading">提交</el-button>
</div>
</el-dialog>
<!--新增界面-->
<el-dialog title="新增"
:visible.sync="addFormVisible"
v-model="addFormVisible"
:close-on-click-modal="false">
<el-form :model="addForm" label-width="80px" :rules="addFormRules" ref="addForm">
<el-form-item label="角色名" prop="RoleName">
<el-input v-model="addForm.RoleName" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="状态" prop="Enabled">
<el-select v-model="addForm.Enabled" placeholder="请选择角色状态">
<el-option label="激活" value="true"></el-option>
<el-option label="禁用" value="false"></el-option>
</el-select>
</el-form-item>
<el-form-item label="说明" prop="Description">
<el-input v-model="addForm.Description" auto-complete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="addFormVisible = false">取消</el-button>
<el-button type="primary" @click.native="addSubmit" :loading="addLoading">提交</el-button>
</div>
</el-dialog>
</section>
</template>
<script>
import util from "../../js/date";
import { getRoleListPage, removeRole, editRole, addRole } from "../../js/api";
import VuePagination from '@/components/Pager'
export default {
name: 'Users',
components: { "VuePagination": VuePagination },
data() {
return {
filters: {
name: ""
},
datalist: [],
statusList: [
{ name: "激活", value: "true" },
{ name: "禁用", value: "false" }
],
total: 0,
page: 1,
listLoading: false,
sels: [], //列表选中列
currentRow: null,
addDialogFormVisible: false,
editFormVisible: false, //编辑界面是否显示
editLoading: false,
editFormRules: {
RoleName: [{ required: true, message: "请输入角色名", trigger: "blur" }],
Enabled: [{ required: true, message: "请选择状态", trigger: "blur" }]
},
//编辑界面数据
editForm: {
Id: 0,
CreateBy: "",
RoleName: "",
Description: "",
Enabled: false
},
addFormVisible: false, //新增界面是否显示
addLoading: false,
addFormRules: {
RoleName: [{ required: true, message: "请输入角色名", trigger: "blur" }],
Enabled: [{ required: true, message: "请选择状态", trigger: "blur" }]
},
//新增界面数据
addForm: {
CreateBy: "",
CreateId: 0,
RoleName: "",
Description: "",
Enabled: true
},
pagination: {
pageSize: 2, // 显示的条数
totals: 0, // 总数
currentPage: 1 // 当前第几页
},
};
},
methods: {
// 改变每页的显示数量
handleSizeChange(val) {
this.pagination.pageSize = val.pageSize;
this.getRoles()
},
// 翻页
handleCurrentChange(val) {
val.totals = this.pagination.totals;
this.pagination = {
...val,
};
this.getRoles()
},
selectCurrentRow(val) {
this.currentRow = val;
},
formatCreateTime: function (row, column) {
return !row.CreateTime || row.CreateTime == ""
? ""
: util.formatDate.format(new Date(row.CreateTime), "yyyy-MM-dd");
},
//获取列表
getRoles() {
let _this = this;
let para = {
page: _this.pagination.currentPage,
intPageSize: _this.pagination.pageSize,
key: this.filters.name
};
this.listLoading = true;
getRoleListPage(para).then(res => {
this.total = res.data.response.dataCount;
this.datalist = res.data.response.data;
this.pagination.totals = res.data.response.dataCount;
this.pagination.currentPage = res.data.response.data;
this.listLoading = false;
});
},
//删除
handleDel() {
let row = this.currentRow;
if (!row) {
this.$message({
message: "请选择要删除的一行数据!",
type: "error"
});
return;
}
this.$confirm("确认删除该记录吗?", "提示", {
type: "warning"
})
.then(() => {
this.listLoading = true;
let para = { id: row.Id };
removeRole(para).then(res => {
if (util.isEmt.format(res)) {
this.listLoading = false;
return;
}
this.listLoading = false;
if (res.data.success) {
this.$message({
message: "删除成功",
type: "success"
});
} else {
this.$message({
message: res.data.msg,
type: "error"
});
}
this.getRoles();
});
})
.catch(() => { });
},
//显示编辑界面
handleEdit() {
let row = this.currentRow;
if (!row) {
this.$message({
message: "请选择要编辑的一行数据!",
type: "error"
});
return;
}
this.editFormVisible = true;
this.editForm = Object.assign({}, row);
this.editForm.Enabled = this.editForm.Enabled ? "true" : "false";
},
//显示新增界面
handleAdd() {
this.addFormVisible = true;
this.addForm = {
CreateBy: "",
RoleName: "",
Enabled: ""
};
},
//编辑
editSubmit: function () {
this.$refs.editForm.validate(valid => {
if (valid) {
this.$confirm("确认提交吗?", "提示", {}).then(() => {
this.editLoading = true;
let para = Object.assign({}, this.editForm);
para.Enabled = para.Enabled === 'true';
editRole(para).then(res => {
if (util.isEmt.format(res)) {
this.editLoading = false;
return;
}
if (res.data.success) {
this.editLoading = false;
this.$message({
message: res.data.msg,
type: "success"
});
this.$refs["editForm"].resetFields();
this.editFormVisible = false;
this.getRoles();
} else {
this.$message({
message: res.data.msg,
type: "error"
});
}
});
});
}
});
},
//新增
addSubmit: function () {
let _this = this;
this.$refs.addForm.validate(valid => {
if (valid) {
this.$confirm("确认提交吗?", "提示", {}).then(() => {
this.addLoading = true;
let para = Object.assign({}, this.addForm);
//var user = JSON.parse(window.localStorage.user);
//if (user && user.uID > 0) {
para.CreateId = 1;
para.CreateBy = "";
//} else {
// this.$message({
// message: "用户信息为空,先登录",
// type: "error"
// });
// _this.$router.replace(
// _this.$route.query.redirect ? _this.$route.query.redirect : "/"
// );
//}
para.Enabled = para.Enabled=== 'true';
addRole(para).then(res => {
if (util.isEmt.format(res)) {
this.addLoading = false;
return;
}
if (res.data.success) {
this.addLoading = false;
this.$message({
message: res.data.msg,
type: "success"
});
this.$refs["addForm"].resetFields();
this.addFormVisible = false;
this.getRoles();
} else {
this.$message({
message: res.data.msg,
type: "error"
});
}
});
});
}
});
}
},
mounted() {
this.getRoles();
}
}
</script>
今天碰到一个很大的坑,花了点时间解决,调用POST方法时,总是报400错误,刚开始以为是数据格式的问题,试了各种方法,不行。最后,最后,竟然发现是字段类型的问题,Enabled在实体里定义的是bool型,传"true"就不行,改成true就可以了。这一点还是想不通,ajax传值一直都是这样传的,为什么没办法自行匹配转换呢?
在新增和修改的保存方法里加了以下就解决了:
para.Enabled = para.Enabled=== 'true';
四、分页组件
<template> <div class="page-wrapper clearfix"> <div class="page-info fl"> <span class="item-count h50"> 总共 <span>{{totals}}</span>条, </span> <span class="h50"> <span>{{totalPages}}</span>页 </span> </div> <div class="page-tab fl clearfix"> <button class="fl h50 cursor" :class="{canNot:currentPage==1}" @click="firstPage" :disabled="preDisabled"> 首页 </button> <button class="fl h50 cursor" :class="{canNot:currentPage==1}" @click="prePage" :disabled="preDisabled"> 上一页 </button> <ul class="fl"> <li v-for="(item,index) in itemArr" :key="index" class="cursor" @click="changePage(item)" :class="{activePage:currentPage=== item}">{{item}}</li> </ul> <button class="fl h50 cursor" @click="nextPage" :class="{canNot:currentPage==totalPages}" :disabled="nextDisabled"> 下一页 </button> <button class="fl h50 cursor" :class="{canNot:currentPage==totalPages}" :disabled="nextDisabled" @click="lastPage"> 尾页 </button> </div> <div class="items-choose fl clearfix"> <span class="fl h50">每页</span> <div class="items-show fl" @click="handleChooseNumClick"> <input v-model="pageSize" class="chooseNum" @blur="blur" readonly /> <div class="per-page-items"> <!-- <input type="text" class="input-item-num"> --> <ul class="items-num" v-show="itemsShow"> <li v-for="(item,index) in pageSizeSettings" :key="index" @click.stop="chooseNum(item)">{{item}}</li> </ul> </div> </div> </div> </div> </template> <script> export default { name: "VuePagination", props: { pageSize: { // 每页显示数量 default: 0, type: Number, }, totals: { // 总数 default: 0, type: Number, }, tab: { type: Boolean, default: false, }, pageSizeSettings: { // 配置下拉 选pageSize type: Array, default() { return [10, 20, 50, 100]; }, }, }, data() { return { itemsShow: false, // 控制每页条数下拉框 itemArr: [], // 显示页数, nextDisabled: null, preDisabled: "disabled", totalPages: 1, // 默认页数 currentPage: 1, size: this.pageSize, // 获取每页数量 }; }, computed: { pageNum() { // 由于父组件传递过来的属性 子组件的钩子里面不能直接使用 用计算属性代替接收 let a = this.pageSize; return a; }, pageItems() { let b = this.totals; return b; }, }, created() { this.pages(); }, methods: { chooseNum(item) { // 改变pageSize this.itemsShow = false; this.$emit("size-change", { pageSize: item, }); }, handleChooseNumClick() { this.itemsShow = !this.itemsShow; }, blur() { var that = this; setTimeout(function () { that.itemsShow = false; }, 200); }, changePage(page) { // 切换页数 this.currentPage = page; this.pages(); }, nextPage() { // 下一页 if (this.currentPage <= this.totalPages - 1) { this.currentPage++; } }, prePage() { // 上一页 if (this.currentPage > 1) { this.currentPage--; } }, firstPage() { // 首页 this.currentPage = 1; }, lastPage() { // 尾页 this.currentPage = this.totalPages; }, pages() { // 页数改变的逻辑 this.itemArr = []; // 每次改变得清空数组 this.totalPages = Math.ceil(this.pageItems / this.pageNum); this.preDisabled = this.currentPage === 1 ? "disabled" : null; this.nextDisabled = this.currentPage === this.totalPages ? "disabled" : null; let start = this.currentPage - 2 > 1 ? this.currentPage - 2 : 1; let end = this.currentPage > 3 ? this.totalPages - this.currentPage >= 2 ? this.currentPage + 2 : this.totalPages : 5; start = this.totalPages - this.currentPage >= 2 ? start : end - 4; if (this.totalPages <= 5) { start = 1; end = this.totalPages; } for (let i = start; i <= end; i++) { this.itemArr.push(i); } }, }, watch: { pageNum() { // 每页数量变化后传递出 pageSize 重新请求数据 this.currentPage = 1; // 改变每页数据 页码回到初始值 this.pages(); this.$emit("size-change", { pageSize: this.pageNum, }); }, currentPage() { // 当前页数变化后 传递出当前页码 重新请求数据 this.pages(); this.$emit("current-change", { pageSize: this.pageNum, currentPage: this.currentPage, }); }, totals() { // 数据是异步加载的 组件刚开始totals是默认的是渲染不了的 this.pages(); }, tab() { // 点击切换条件筛选 重置currentPage this.currentPage = 1; }, }, }; </script> <style> * { padding: 0; margin: 0; } ul, li { list-style: none; } .clearfix:after { content: "."; height: 0; display: block; visibility: hidden; clear: both; overflow: hidden; } .cursor { cursor: pointer; } .clearfix { zoom: 1; } .page-wrapper .fl { float: left; } .page-wrapper { font-size: 14px; color: #5e6470; } .h50 { display: inline-block; height: 30px; line-height: 30px; padding: 0 12px; border: 1px solid #eaedf1; } .page-wrapper .page-tab li { float: left; width: 30px; height: 30px; text-align: center; line-height: 30px; border: 1px solid #eaedf1; box-sizing: border-box; } .page-wrapper .page-info { margin-right: 6px; } .page-wrapper .page-info .h50 { border: none; padding: 0; } .items-choose .h50 { padding: 0; border: none 0; border-top: 1px solid #eaedf1; border-bottom: 1px solid #eaedf1; box-sizing: border-box; padding: 0 6px; } .items-choose .items-show { height: 30px; width: 74px; position: relative; box-sizing: border-box; border: 1px solid #eaedf1; position: relative; } .items-choose .items-show input { height: 100%; width: 100%; text-align: center; } .items-choose .items-show:after { content: ""; position: absolute; height: 0; border: 4px solid transparent; border-top: 6px solid #c4ccc5; top: 50%; right: 10px; transform: translate3d(-50, -50, 0); cursor: pointer; } .items-choose .items-num { width: 100%; position: absolute; bottom: 42px; border: 1px solid #eaedf1; z-index: 100; background: #f5f7fa; z-index: 999; } .items-choose .items-num li { padding: 10px 0 10px 6px; font-size: 14px; } .items-choose .items-num li:hover { /*background: #1AB394;*/ background: #4a8df0; color: #fff; } .page-wrapper .activePage { color: #fff; /*background: #1AB394;*/ background: #4a8df0; } .canNot { cursor: not-allowed; } .page-wrapper button { background: #fff; font-size: 14px; color: #5e6470; } .chooseNum { cursor: pointer; font-size: 14px; color: #5e6470; } </style>
五、运行效果


浙公网安备 33010602011771号