vue2 表单自定义验证,规则服务端维护
功能描述:
1、基于element ui 自定义表单验证
2、vuex 缓存后端返回数据
3、基于服务端接口返回验证规则适用于,第三方规则
1、路由守卫前,触发登陆成功获取,动态验证规则集合,存放到vuex
// 全局前置守卫 router.beforeEach((to, from, next) => { console.log("路由守卫触发:从", from.path, "到", to.path); //请求接口获取后台规则 逻辑判断...直接处理响应结构如下 规则字段【pattern,message】后边需要字段不可少 const backendRules = { phone: [ { pattern: /\S/, message: "手机号不能为空", }, { // 自定义验证规则 pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号格式", }, ], password: [ { pattern: /\S/, message: "密码不能为空", trigger: "blur", }, { pattern: /^.{8,20}$/, message: "密码长度需在8-20位之间", }, { pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,20}$/, message: "密码需包含大小写字母、数字和特殊字符", }, ], confirmPassword: [ { pattern: /\S/, message: "请确认密码", }, { pattern: /\S/, message: "两次输入的密码不一致", deps: ["password"], // 跨字段校验(与密码一致) params: {}, // 预留函数参数 }, ], }; store.dispatch('dyRule/ADD_RULES',backendRules) // 必须调用 next() 来 resolve 这个钩子 next(); });
vuex.---- src/store/ModuleRule/index.js
const Rules = { namespaced: true, // 开启命名空间,避免模块间命名冲突 state: { rulesList: {}, // 存放后台返回动态验证规则,假设有 2,3百个,类似码值 }, getters: { getRules(state) { return state.rulesList; }, }, mutations: { SET_RULES(state, rule) { state.rulesList = rule; }, }, actions: { ADD_RULES({ commit }, rule) { commit("SET_RULES", rule); }, }, }; export default Rules;
store/index.js. 引用
/* * @Description: */ // store/index.js import Vue from "vue"; import Vuex from "vuex"; import ModuleA from "./ModuleA"; import ModuleB from "./ModuleB"; import getters from "./getters"; import Rules from "./ModuleRule"; Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0, // 示例:计数器状态 permission: ['sys:user:add'], }, getters, mutations: { add(state, num) { state.count += num; }, addPermission(state, vals) { state.permission = vals; }, }, actions: { addUser({ commit }, num) { // this.add(state) commit("add", num); }, }, modules: { cart: ModuleA, // 注册模块,访问时需加模块名:$store.state.cart.items user: ModuleB, dyRule: Rules }, }); export default store;
store/getters.js
const getters = { getCount: (state) => state.count, getCartCount: (state) => state.cart.count, getPermission: state =>state.permission, getDyRule: state => state.dyRule.rulesList } export default getters
页面使用。如果不使用vuex. 页面可以直接看效果 ---注释打开 ---
fetchBackendRules
<template> <el-form :model="form" :rules="elementRules" ref="formRef" label-width="100px" class="form-container" > <el-form-item label="手机号" prop="phone"> <custom-input v-model="form.phone" placeholder="请输入手机号" /> </el-form-item> <el-form-item label="密码" prop="password"> <custom-input v-model="form.password" type="password" placeholder="请输入密码" /> </el-form-item> <el-form-item label="确认密码" prop="confirmPassword"> <custom-input v-model="form.confirmPassword" type="password" placeholder="请确认密码" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSubmit">提交</el-button> <el-button @click="handleReset">重置</el-button> </el-form-item> </el-form> </template> <script> import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; import transformBackendRules2 from "@/utils/ruleTransformer2"; import CustomInput from "./CustomInput/index.vue"; // import axios from 'axios'; export default { name: "DynamicForm", components: { CustomInput, }, computed: { ...mapGetters("dyRule", ["getRules"]), getRules1() { return this.$store.getters.getDyRule; }, }, data() { return { form: { phone: "", password: "", confirmPassword: "", }, elementRules: {}, // 转换后的Element UI规则 }; }, created() { // console.log("getRules", this.getRules); const backRules = this.$store.getters.getDyRule; // console.log("backRules-----", backRules); // console.log('getRules1',this.getRules1) // 初始化时获取后端规则 this.fetchBackendRules(backRules); }, methods: { // 获取后端规则 async fetchBackendRules(backendRules) { try { // const response = await axios.get('/api/form/rules'); // 替换为实际接口地址 // const backendRules = response.data; // 后端返回的规则对象 // 转换规则(传入表单对象,用于跨字段校验) // const backendRules = { // phone: [ // { // pattern: /\S/, // message: "手机号不能为空", // }, // { // // 自定义验证规则 // pattern: /^1[3-9]\d{9}$/, // message: "请输入正确的手机号格式", // }, // ], // password: [ // { // pattern: /\S/, // message: "密码不能为空", // trigger: "blur", // }, // { // pattern: /^.{8,20}$/, // message: "密码长度需在8-20位之间", // }, // { // pattern: // /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,20}$/, // message: "密码需包含大小写字母、数字和特殊字符", // }, // ], // confirmPassword: [ // { // pattern: /\S/, // message: "请确认密码", // }, // { // pattern: /\S/, // message: "两次输入的密码不一致", // deps: ["password"], // 跨字段校验(与密码一致) // params: {}, // 预留函数参数 // }, // ], // }; this.elementRules = transformBackendRules2(backendRules, this.form); } catch (error) { console.error("获取后端规则失败:", error); // fallback:使用默认规则(可选) this.elementRules = this.getDefaultRules(); } }, // 表单提交 handleSubmit() { this.$refs.formRef.validate((valid) => { if (valid) { console.log("表单校验通过,提交数据:", this.form); // 此处执行提交逻辑(如调用接口) } else { console.log("表单校验失败"); return false; } }); }, // 重置表单 handleReset() { this.$refs.formRef.resetFields(); // this.$refs.formRef.clearValidate(); // 清除校验提示 // Object.keys(this.form).forEach((key) => { // this.form[key] = ""; // 清空表单数据 // }); }, // 可选:定义默认规则(当后端规则获取失败时使用) getDefaultRules() { return { username: [ { required: true, message: "用户名不能为空", trigger: "blur" }, ], // 其他字段的默认规则... }; }, }, }; </script> <style scoped> .form-container { width: 500px; margin: 20px auto; padding: 20px; border: 1px solid #ebeef5; border-radius: 4px; } </style>
ruleTransformer2.js
// src/utils/ruleTransformer.js /** * 将后端规则转换为Element UI的rules格式 * @param {Object} backendRules - 后端返回的规则对象 * @param {Object} form - 表单数据对象(用于跨字段校验) * @returns {Object} - 转换后的Element UI rules */ export default function transformBackendRules2(backendRules, form) { const elementRules = {}; console.log("form", form); // 后台返回验证集合包括需要验证 // form:{ // name:'', //} //1、当前form 数据是否在 后台返回集合里边,有就需要验证 Object.keys(form).forEach((propName) => { const backendRule = backendRules[propName] || ""; if (backendRule) { // 属性存在,组装element验证规范 elementRules[propName] = backendRule.map((rule) => { if (rule.pattern) { return { required: true, // trigger: rule.trigger || 'blur', trigger:['change','blur'], validator: (_rule, value, callback) => { const ruleStr = rule.pattern; // console.log("valuevalue", value); if (!ruleStr.test(value)) { return callback(new Error(rule.message)); } else if (rule.deps) { // 验证两个属性有依赖,密码及确认密码 const [otherField] = rule.deps; // 解构 if (form[otherField] !== value) { return callback(new Error(rule.message)); } } else { callback(); } }, }; } else { return rule; } }); } }); console.log("elementRules", elementRules); return elementRules; }
浙公网安备 33010602011771号