美文网首页前端练习小模块前端开发那些事儿
四、vue+ElementUI开发后台管理模板—方法指令、接口数

四、vue+ElementUI开发后台管理模板—方法指令、接口数

作者: 吃自己家大米 | 来源:发表于2020-06-01 07:44 被阅读0次

    (获取本节完整代码 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、获取接口数据、模拟数据—— axiosmockjs

    (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开发后台管理模板—精确到按钮的权限控制

    vue3 + vite + ElementPlus开发后台管理模板

    vue实践1.1 企业官网——prerender-spa-plugin预渲染

    相关文章

      网友评论

        本文标题:四、vue+ElementUI开发后台管理模板—方法指令、接口数

        本文链接:https://www.haomeiwen.com/subject/qanzohtx.html