MST

星途 面试题库

面试题:Vue表单绑定复杂验证逻辑的动态规则生成与复用

在一个大型Vue项目中,有多种类型的表单,每种表单都有一些复杂且部分相似的验证逻辑。要求能够根据表单类型动态生成验证规则,并且可以复用这些规则。例如,用户注册表单和用户信息修改表单都有用户名、密码字段,但注册表单要求用户名不能与已存在的用户名重复,而修改表单要求用户名不能与原用户名相同且不能与其他已存在用户名重复。请设计一个通用的解决方案,阐述架构设计思路,并给出核心代码示例。
29.6万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

架构设计思路

  1. 规则抽象:将表单验证规则进行抽象,提取出相似部分和不同部分。把通用的验证逻辑(如用户名长度、密码强度等)与特定表单的验证逻辑(如注册和修改时用户名的唯一性判断)分开。
  2. 工厂模式:使用工厂模式来根据表单类型动态生成验证规则。创建一个验证规则工厂函数,根据传入的表单类型参数,返回对应的验证规则对象。
  3. 规则复用:对于相似的验证逻辑,封装成独立的函数或模块,在不同表单验证规则中复用。

核心代码示例

  1. 通用验证函数
// 验证用户名长度
function validateUsernameLength(rule, value, callback) {
  if (value.length < 3 || value.length > 20) {
    callback(new Error('用户名长度需在3到20个字符之间'));
  } else {
    callback();
  }
}

// 验证密码强度
function validatePasswordStrength(rule, value, callback) {
  const strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})');
  if (!strongRegex.test(value)) {
    callback(new Error('密码强度不够,至少8位,包含大小写字母、数字和特殊字符'));
  } else {
    callback();
  }
}
  1. 验证规则工厂函数
function createValidationRules(formType, existingUsernames, originalUsername) {
  const rules = {
    username: [
      { validator: validateUsernameLength, trigger: 'blur' }
    ],
    password: [
      { validator: validatePasswordStrength, trigger: 'blur' }
    ]
  };

  if (formType ==='register') {
    rules.username.push({
      validator: (rule, value, callback) => {
        if (existingUsernames.includes(value)) {
          callback(new Error('用户名已存在'));
        } else {
          callback();
        }
      },
      trigger: 'blur'
    });
  } else if (formType === 'update') {
    rules.username.push({
      validator: (rule, value, callback) => {
        if (value === originalUsername) {
          callback();
        } else if (existingUsernames.includes(value)) {
          callback(new Error('用户名已存在'));
        } else {
          callback();
        }
      },
      trigger: 'blur'
    });
  }

  return rules;
}
  1. 在Vue组件中使用
<template>
  <form>
    <el-form :model="formData" :rules="validationRules" ref="form">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="formData.username"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" v-model="formData.password"></el-input>
      </el-form-item>
      <el-button type="primary" @click="submitForm">提交</el-button>
    </el-form>
  </form>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        username: '',
        password: ''
      },
      existingUsernames: ['user1', 'user2'],
      originalUsername: 'user3',
      validationRules: null
    };
  },
  created() {
    // 假设这里是注册表单
    this.validationRules = createValidationRules('register', this.existingUsernames);
  },
  methods: {
    submitForm() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          console.log('表单验证通过');
        } else {
          console.log('表单验证失败');
        }
      });
    }
  }
};
</script>