四、vue+ElementUI开发后台管理模板—方法指令、接口数
(获取本节完整代码 GitHub/chizijijiadami/vue-elementui-4)
0、写在前面
这篇文章主要内容包括:
● 自定义全局过滤器
● 自定义全局表单验证
● 获取接口数据、模拟数据——axios+Mockjs 【关联:axios源码学习到使用】
● 跨域访问数据、服务器打包部署——phpstudy、PHP
1、自定义全局方法
(1)状态值过滤
我们数据库里记录一个表单的状态经常用数字1234等表示,在这里我们可以统一记录过滤显示。
● 新建 src>common>filter>status.js
// 订单状态
export function orderStatusFilters(val) {
if (Number(val) === 0) {
return '未付款'
} else if (Number(val) === 1) {
return '待发货'
} else if (Number(val) === 2) {
return '待收货'
} else if (Number(val) === 3) {
return '未评价'
} else if (Number(val) === 4) {
return '已完成'
} else if (Number(val) === 5) {
return '退款'
} else if (Number(val) === 6) {
return '退货退款'
} else if (Number(val) === -1) {
return '已取消'
}
}
// 审批状态
export function approvalStatusFilters(val) {
if (Number(val) === 0) {
return '未开始'
} else if (Number(val) === 1) {
return '审批中'
} else if (Number(val) === 2) {
return '已批准'
} else if (Number(val) === 3) {
return '已拒绝'
}
}
新建 src>common>filter>index.js
// 状态
import * as status from './status'
export default {
...status
}
● 使用
修改 main.js
+ // 注册全局filters过滤器
+ import filters from './common/filters'
+ Object.keys(filters).forEach(key => {
+ Vue.filter(key, filters[key])
+ })
修改 src>pages>Index>index.vue
+ <p>{{3|orderStatusFilters}}</p>
看下截图,转换成功。
(2)表单验证
● 新建 src>common>validate>validate.js
/* 邮箱 */
export function validateEmail(email) {
const re = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/
if (email.length === 0) {
return { status: false, msg: '邮箱不能为空!' }
}
if (!re.test(email)) {
return { status: false, msg: '请输入有效的邮箱!' }
}
return { status: true }
}
// 验证手机号
export function validateMobile(mobile) {
if (mobile.length !== 11) {
return { status: false, msg: '请输入有效的手机号码,需是11位!' }
}
var myreg = /^(1[0-9]{10})$/
if (!myreg.test(mobile)) {
return { status: false, msg: '请输入有效的手机号码!' }
}
return { status: true }
}
// 验证身份证
export function validateIDCard(id) {
// 1 "验证通过!", 0 //校验不通过
var format = /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/
// 号码规则校验
if (!format.test(id)) {
return { status: false, msg: '身份证号码不合规' }
}
// 区位码校验
// 出生年月日校验 前正则限制起始年份为1900;
var year = id.substr(6, 4) // 身份证年
var month = id.substr(10, 2) // 身份证月
var date = id.substr(12, 2) // 身份证日
var time = Date.parse(month + '-' + date + '-' + year) // 身份证日期时间戳date
var nowTime = Date.parse(new Date()) // 当前时间戳
var dates = new Date(year, month, 0).getDate() // 身份证当月天数
if (time > nowTime || date > dates) {
return { status: false, msg: '出生日期不合规' }
}
// 校验码判断
var c = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] // 系数
var b = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] // 校验码对照表
var idArray = id.split('')
var sum = 0
for (var k = 0; k < 17; k++) {
sum += parseInt(idArray[k]) * parseInt(c[k])
}
if (idArray[17].toUpperCase() !== b[sum % 11].toUpperCase()) {
return { status: false, msg: '身份证校验码不合规' }
}
return { status: true, msg: '校验通过' }
}
新建 src>common>validate>regCheck.js
import {
// 11位手机号
validateMobile,
// 邮箱
validateEmail,
// 身份证
validateIDCard
} from './validate'
export const validatorCode = {
// 非空校验
checkNotNull(rule, value, callback) {
if (
String(value).replace(/^\s+|\s+$/gm, '') === '' ||
(value instanceof Array && value[0] === '') ||
value === null ||
value === undefined
) {
callback(new Error(this.message || (this.name || '内容') + '不能为空!'))
} else {
callback()
}
},
// 11位手机号
checkMobile(rule, value, callback) {
if (value !== null && value !== '') {
if (!validateMobile(value).status) {
callback(new Error(validateMobile(value).msg))
} else {
callback()
}
} else {
callback()
}
},
// 邮箱
checkEmail(rule, value, callback) {
if (value !== null && value !== '') {
if (!validateEmail(value).status) {
callback(new Error(validateMobile(value).msg))
} else {
callback()
}
} else {
callback()
}
},
// 身份证号
checkIdCard(rule, value, callback) {
if (value !== null && value !== '') {
if (!validateIDCard(value).status) {
callback(new Error(validateMobile(value).msg))
} else {
callback()
}
} else {
callback()
}
},
}
新建 src>common>validate>index.js
import { validatorCode } from './regCheck.js'
export default function install(Vue) {
Vue.prototype.regCheck = function (item) {
let rules = []
let _trigger = item.trigger || 'blur'
let _required = item.required || false
let _type = item.type
if (_required) {
rules.push({
required: true,
validator: validatorCode.checkNotNull.bind(item),
trigger: _trigger
})
}
if (_type) {
switch (_type) {
// 手机校验
case 'mobile':
rules.push({
required: _required,
validator: validatorCode.checkMobile,
trigger: _trigger
})
break
// 邮箱校验
case 'email':
rules.push({
required: _required,
validator: validatorCode.checkEmail,
trigger: _trigger
})
break
// 身份证校验
case 'idCard':
rules.push({
required: _required,
validator: validatorCode.checkIdCard,
trigger: _trigger
})
break
default:
rules.push({})
break
}
}
return rules
}
}
● 使用
修改 main.js
+ // 全局校验
+ import Validate from '@/common/validate/index.js'
+ Vue.use(Validate)
修改 src>pages>Index>index.vue
+ <div>
+ <el-form :model="form" ref="form" label-width="100px">
+ <el-form-item
+ prop="mobile"
+ label="手机号码"
+ :rules="regCheck({required:true,type:'mobile',message:'手机号码为必输项'})"
+ >
+ <el-input v-model="form.mobile"></el-input>
+ </el-form-item>
+ <el-form-item
+ prop="email"
+ label="邮箱"
+ :rules="regCheck({required:true,type:'email',name:'邮箱'})"
+ >
+ <el-input v-model="form.email"></el-input>
+ </el-form-item>
+ <el-form-item prop="idCard" label="身份证号" :rules="regCheck({required:true,type:'idCard'})">
+ <el-input v-model="form.idCard"></el-input>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="submitForm('form')">提交</el-button>
+ <el-button @click="resetForm('form')">重置</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ methods: {
+ submitForm(formName) {
+ this.$refs[formName].validate(valid => {
+ if (valid) {
+ alert("submit!");
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ },
+ resetForm(formName) {
+ this.$refs[formName].resetFields();
+ },
+ }
看下效果,可以自己改着各种值试一下。
2、获取接口数据、模拟数据—— axios+mockjs
(1) axios 数据请求
● 安装
yarn add axios
● 添加拦截器
新建 common>utils>axiosApi.js
import axios from 'axios'
import ErrorMessage from './errorMessage'
import { MessageBox } from 'element-ui'
var instance = axios.create({
baseURL: '',
timeout: 5000
});
// 添加请求拦截器
instance.interceptors.request.use(
// 在发送请求之前做些什么
config => {
config.headers['version'] = '1'
return config
},
error => {
Promise.reject(error)
}
);
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
if (response.data.status !== 0) {
return Promise.reject(response)
} else {
return Promise.resolve(response)
}
}, function (error) {
// 对响应错误做点什么
if (!error.response) {
// 服务器请求失败时错误提示
MessageBox({
message: `请求超时${ErrorMessage.API_ERROR_LOAD}`,
showCancelButton: false,
confirmButtonText: '确定',
type: 'error',
callback() { }
})
} else {
let errorStatus = error.response.status
switch (errorStatus) {
case 400:
error.message = ErrorMessage.STATUS_400
break
case 401:
error.message = ErrorMessage.STATUS_401
break
case 403:
error.message = ErrorMessage.STATUS_403
break
case 404:
error.message = ErrorMessage.STATUS_404
break
case 408:
error.message = ErrorMessage.STATUS_408
break
case 500:
error.message = ErrorMessage.STATUS_500
break
case 501:
error.message = ErrorMessage.STATUS_501
break
case 502:
error.message = ErrorMessage.STATUS_502
break
case 503:
error.message = ErrorMessage.STATUS_503
break
case 504:
error.message = ErrorMessage.STATUS_504
break
case 505:
error.message = ErrorMessage.STATUS_505
break
default:
}
MessageBox({
message: error.response.config.url + " " + error.message,
showCancelButton: false,
confirmButtonText: '确定',
type: 'error',
callback() {
if (errorStatus == 404) {
console.log('44444444444');
}
}
})
}
return Promise.reject(error);
});
export default function (config) {
let _config = {
url: '',
method: 'get'
}
_config = Object.assign(_config, config)
_config.params = _config.params
? _config.filter
? _config.filter.request(JSON.parse(JSON.stringify(_config.params)))
: _config.params
: ''
if (_config.method.toLowerCase() != 'get') {
_config.data = _config.params
_config.params = {}
}
return new Promise((resolve, reject) => {
return instance(_config)
.then(response => {
resolve(_config.filter ? _config.filter.response(response.data) : response.data)
})
.catch(error => {
reject(error)
})
})
}
新建 common>utils>errorMassage.js
const ErrorMessage = {
API_ERROR_LOAD: '服务器无响应!',
STATUS_400: '请求错误!',
STATUS_401: '登录超时!',
STATUS_403: '拒绝访问!',
STATUS_404: '请求地址出错!',
STATUS_408: '请求超时!',
STATUS_500: '服务器内部错误!',
STATUS_501: '服务未实现!',
STATUS_502: '网关错误!',
STATUS_503: '服务不可用!',
STATUS_504: '网关超时!',
STATUS_505: 'HTTP版本不受支持!'
}
export default ErrorMessage
● 使用
新建 src>data>api>Index>index.js
import axiosApi from '@/common/utils/axiosApi'
import * as filter from './filter'
export function getList(params) {
return axiosApi({
url: '/list',
method: 'get',
filter: filter.getList,
params: params
})
}
export function getTitle(params) {
return axiosApi({
url: '/title',
method: 'get',
filter: filter.getTitle,
params: params
})
}
新建 src>data>api>Index>filter.js,过滤处理数据
export const getList = {
request(params) {
return params
},
response(data) {
return data
}
}
export const getTitle= {
request(params) {
return params
},
response(data) {
return data
}
}
修改 src>pages>Index>index.vue
+ import * as api from "data/api/Index";
export default {
name: "IndexIndex",
data() {
return {
form: {
mobile: "",
email: "",
idCard: ""
}
};
},
+ created() {
+ this.getList();
+ },
methods: {
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
alert("submit!");
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
+ getList() {
+ api.getList().then(res => {
+ console.log(res);
+ });
+ }
}
}
因为我们这个项目里没有 /list 这个接口,所以报错了,一般前后分离开发是同步进行的,为了方便前端开发,我们就得模拟接口及其返回数据,下面我们用 mockjs 来实现。
(2)mockjs 模拟接口数据
● 安装
yarn add mockjs -D
● 使用
新建 src>data>mock>index.js
const Mock = require("mockjs");
// 使用mockjs模拟数据
let dataList = Mock.mock({
// 属性 list 的值是一个数组,其中含有 1 到 10 个元素
"list|1-10": [
{
// 属性 id 是一个自增数,起始值为 1,每次增 1
"id|+1": 1,
name: "@FIRST",
creatTime: "@datetime"
}
]
});
Mock.mock("/list", "get", () => {
return {
status: 0,
data: dataList,
message: "成功"
};
});
修改 main.js
+ //mockj数据
+ import 'data/mock'
刷新页面,可以看到控制台打印的信息。我们在页面中使用显示一下
修改 src>pages>Index>index.vue
+ <div>
+ <p v-for="item in list" :key="item.id">{{item.name}}</p>
+ </div>
data() {
return {
form: {
mobile: "",
email: "",
idCard: ""
},
+ list: []
};
},
getList() {
api.getList().then(res => {
- console.log(res);
+ this.list=res.data.list
});
}
如图:
到这里我们的全局方法指令跟接口数据就结束了,下一篇写完到按钮级别的权限控制这个后台管理模板也结束了。
另外如果你不想用mock数据,可以自己写服务接口,我们前端用nodejs或者php都是挺方便的,nodejs后面会写专门的文章介绍,下面介绍php,这里也同样适用跨域获取第三方接口数据。
3、拓展——结合 phpstudy 使用PHP写接口
phpstudy的安装使用见官网或者参考 一、vue入门基础开发—手把手教你用vue开发 文章最后即第四大点的第(3)部分的拓展。
在这里我们新建一个网站。
在vscode中打开 WWW 文件夹,新建文件 index.php
<?php
$data = array();
$data['status'] = 0;
$data['list'] = array();
$data['list'][0] = ['name' => 'ha'];
$data['list'][1] = ['name' => 'hei'];
exit(json_encode($data));
修改 .env.development
NODE_ENV = 'development'
VUE_APP_BASE_API = 'http://192.168.0.1'
+ VUE_APP_CROSS_DOMAIN='http://localhost:6789'
修改 src>data>api>Index>index.js,注意看这里有个注释掉的语句,如果是打包部署到这个新建的网站里就用注释掉的那个语句,因为我们没有配置生产环境里CROSS_DOMAIN。当然,如果你在 .env.produntion 里同样配置了CROSS_DOMAIN,那就还用没注释的这条就好。
+ export function getCrossDomainList(params) {
+ return axiosApi({
+ url: process.env.VUE_APP_CROSS_DOMAIN+"/index.php",
+ //url: (process.env.NODE_ENV === "development" ? process.env.VUE_APP_CROSS_DOMAIN : "") + "/index.php",
+ method: 'get',
+ filter: filter.getCrossDomainList,
+ params: params
+ })
+ }
修改 src>data>api>Index>filter.js,假设这里返回的人名都要大写,我们在这里处理。
+ export const getCrossDomainList = {
+ request(params) {
+ return params
+ },
+ response(data) {
+ for (let i = 0; i < data.list.length; i++) {
+ data.list[i].name = data.list[i].name.toUpperCase()
+ }
+ return data
+ }
+ }
使用,修改 src>pages>Index>index.vue
created() {
this.getList();
+ this.getCrossDomainList();
},
methods:{
......
+ getCrossDomainList() {
+ api.getCrossDomainList().then(res => {
+ console.log(res);
+ });
+ }
}
第三方接口方式
运行一下,控制台里看到报跨域了。
这就需要在服务器配置里修改,phpstudy_pro\Extensions\Apache2.4.39\conf\vhosts 路径下找到我们新建网站的配置文件 ,打开添加允许跨域访问语句。
Header set Access-Control-Allow-Origin http://localhost:8081
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers *
添加后保存,重新启动Apache服务器生效,再次刷新页面,获取成功,如下图
打包部署方式
这里不存在跨域问题,但是看到控制台是没有信息输出的,因为我们在第一篇里说过生产环境去console的插件 babel-plugin-transform-remove-console 。
感谢阅读,,喜欢的话点个赞吧:)更多内容请关注后续文章。
一、vue入门基础开发—手把手教你用vue开发
二、vue+ElementUI开发后台管理模板—布局
三、vue+ElementUI开发后台管理模板—功能、资源、全局组件
五、vue+ElementUI开发后台管理模板—精确到按钮的权限控制