• 基于策略模式简单实现element表单校验


    什么是策略模式

    在策略模式中定义了一系列算法,将每一个算法封装起来,并让他们可以互相替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。

    策略模式的优点:

    • 策略模式利用组合、委托和多态等技术思想,可以有效的避免多种条件选择语句
    • 策略模式提供了对开放封闭原则的完美支持,将算法封装在独立的strategy中,使得它易于切换,易于理解,易于拓展
    • 策略模式中的算法也可以服用在系统的其他地方,从而避免许多重复的复制黏贴工作
    • 在策略模式利用组合和委托来让Context拥有执行算法的能力,这也是i继承一种更轻便的替代方按

    缺点:

    • 编写难度加大,代码量变多,这是最直观的一个缺点,但也算不上缺点,毕竟不能以代码量多少衡量代码质量
    • 首先,使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比把它们负责的逻辑堆砌在Content中要好
    • 其次要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy。这是违反最少知识原则的

    现在我们有一个表单校验需求,在提交按钮之前,有如下几条校验规则:

    • 账号不能为空
    • 密码长度最少7位

    一开始我可能会这么写

    <template>
      <div>
        <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="账号">
        <el-input v-model="form.account"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input type="textarea" v-model="form.passowrd"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">登录</el-button>
      </el-form-item>
    </el-form>
      </div>
    </template>
    <script>
    export default {
      data(){
        return {
          form: {
              account: '',
              passowrd: '' 
            },
        }
      },
      methods:{
        onSubmit(){
          let {account,passowrd} = this.form;
          if(!account){
            this.$message.error('请输入账号')
          }else if(passowrd.length<7){
            this.$message.error('密码长度不能低于7位')
          }else{
            this.$message.success('表单校验成功')
          }
        }
      }
    }
    </script>
    
    

    这是一种很常见的编码方式,但它有很明显的缺点:

    • 包含了很多if语句,这些语句要覆盖所有的校验规则。
    • 若校验规则有变,需要改动onSubmit校验规则,违反开闭原则
    • 算法复用性差
    下面让我们使用策略模式重构表单校验
    <template>
      <div>
        <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="账号">
        <el-input v-model="form.account"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input type="textarea" v-model="form.passowrd"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">登录</el-button>
      </el-form-item>
    </el-form>
      </div>
    </template>
    <script>
    export default {
      data(){
        return {
          form: {
              account: '',
              passowrd: '' 
            },
            strategies:{
              isNoEmpty(data, key){
                return new Promise((resolve,reject)=>{
                  if(data[key]){
                    resolve()
                  }else{
                    reject('请输入账号')
                  }
                })
              },
              minLength(data,key){
                return new Promise((resolve,reject)=>{
                  if(data[key].length<7){
                    reject('密码最低不能少于7个字')
                  }else{
                    resolve()
                  }
                })
              }
            }
        }
      },
      methods:{
        onSubmit(){
          let {strategies} = this;
          strategies.isNoEmpty(this.form,'account')
          .then(()=>strategies.minLength(this.form,'passowrd'))
          .then(()=>{
            this.$message.success('表单校验成功')
          }).catch(err=>{
            this.$message.error(err)
          })
        }
      }
    }
    </script>
    
    

    让我们把上面代码优化下,实现简单的element表单校验

    <template>
      <div>
        <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="账号">
        <el-input v-model="form.account"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input type="textarea" v-model="form.passowrd"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">登录</el-button>
      </el-form-item>
    </el-form>
      </div>
    </template>
    <script>
    export default {
      data(){
        return {
          form: {
              account: '',
              passowrd: '' 
            },
            rules:{
              account:[
                {methodName:"isNoEmpty",message:'请输入账号'}
              ], 
              passowrd:[
                {methodName:"isNoEmpty",message:'请输入密码'},
                {methodName:"minLength",length:7,message:'密码最低不能少于7位'}
              ],
            },
            strategies:{
              minLength(val,err,length){
                  if(val.length<length){
                    return err;
                  }
              },
              isNoEmpty(val,err){
                if(!val){
                  return err;
                }
              }
            }
        }
      },
      methods:{
        strategiesFun(data){
          let {strategies,rules} = this;
          let err = []
          for(let key in data) {
            rules[key].forEach(item=>{
              let _err = strategies[item.methodName](data[key],item.message,item.length);
              _err && err.push(_err);
            });
          }
          return new Promise((resolve,reject)=>{
            err.length ? reject(err[0]) : resolve()
          })
        },
        onSubmit(){
          this.strategiesFun(this.form)
          .then(()=>{
            this.$message.success('表单校验成功')
          }).catch(err=>{
            this.$message.error(err)
          })
        }
      }
    }
    </script>
    

    比如,某天新增加一个需求,要求账号长度不小于5位数我们只需要在rules对象中增加一条校验规则就行

    rules:{
      account:[
        {methodName:"isNoEmpty",message:'请输入账号'},
        {methodName:"minLength",length:5,message:'账号最低不能少于5位'}
      ], 
      passowrd:[
        {methodName:"isNoEmpty",message:'请输入密码'},
        {methodName:"minLength",length:7,message:'密码最低不能少于7位'}
      ],
    },
    
  • 相关阅读:
    SQL日常维护的语句
    87岁老奶奶用微软自带画图软件绘画 惊艳了世人
    87岁老奶奶用微软自带画图软件绘画 惊艳了世人
    87岁老奶奶用微软自带画图软件绘画 惊艳了世人
    .NET开源项目小功能组件
    .NET开源项目小功能组件
    .NET开源项目小功能组件
    常用 SQL Server 规范集锦
    常用 SQL Server 规范集锦
    常用 SQL Server 规范集锦
  • 原文地址:https://www.cnblogs.com/mengxiangji/p/10990656.html
Copyright © 2020-2023  润新知