0
点赞
收藏
分享

微信扫一扫

Element-ui组件库Form表单_数字类型验证之坑

自由的美人鱼 2022-03-22 阅读 74
前端

项目需求 : 使用的饿了么组件库的 input 框 , 但是想要实现只能输入 数字 的功能,

So 看到了数字类型的验证 , 但今天在项目里对照着示例写都频繁报错 , 简直大无语 。 。 。

所以自己整理一下 , 免得自己以后掉坑 。 。 。

<template>
  <div class="formBox">
    <div class="infos">
      <div class="infoBox">
        <el-form
          :model="numberValidateForm"
          ref="numberValidateForm"
          label-width="100px"
          class="demo-ruleForm"
          label-position="left"
        >
          <el-form-item label="姓名" prop="name" :rules="name">
            <el-input
              v-model="numberValidateForm.name"
              autocomplete="off"
              placeholder="请输入姓名"
            ></el-input>
          </el-form-item>
          <el-form-item label="联系电话" prop="phone" :rules="phone">
            <el-input
              v-model="numberValidateForm.phone"
              autocomplete="off"
              placeholder="请输入电话号码"
            ></el-input>
          </el-form-item>
          <el-form-item label="树龄" prop="number" :rules="number">
            <el-input
              type="number"
              v-model.number="numberValidateForm.number"
              autocomplete="off"
              placeholder="请输入树龄"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="submitForm('numberValidateForm')"
              >提交</el-button
            >
            <el-button @click="resetForm('numberValidateForm')">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>
  </div>
</template>
<script>
const cryptoJs = new CryptoJs();
export default {
  data() {
    let checkValue = (rule, value, callback) => {
      if (!value) {
        return callback(new Error("值不能为空"));
      }
      setTimeout(() => {
        if (!Number.isInteger(value)) {
          callback(new Error("请输入数字值"));
        } else {
          if (value < 1) {
            callback(new Error("值必须大于1"));
          } else {
            callback();
          }
        }
      }, 200);
    };
    return {
      numberValidateForm: {
        name: "", // 姓名
        phone: "", // 电话
        number: null, // 数量
      },
      name: { required: true, message: "姓名不能为空" },
      phone: { required: true, message: "联系电话不能为空" },
      number: [
        { required: true, validator: checkValue, trigger: ["change", "blur"] },
      ],
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          let params = this.numberValidateForm;
          console.log("验证成功,参数为", params);
        } else {
          console.log("数据验证不成功");
          return false;
        }
      });
    },
    //重置
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
  },
};
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>


百度的各种写法 :(希望有一个能用得上吧)

<template>
  <div class="formBox">
    <div class="infos">     
      <div class="infoBox">
        <el-form
          :model="numberValidateForm"
          ref="numberValidateForm"
          label-width="100px"
          class="demo-ruleForm"
          label-position="left"
        >        
        <el-form-item label="姓名" prop="name" :rules="name">
            <el-input
              v-model="numberValidateForm.name"
              autocomplete="off"
              placeholder="请输入姓名"
            ></el-input>
          </el-form-item>
          <el-form-item label="联系电话" prop="phone" :rules="phone">
            <el-input
              v-model="numberValidateForm.phone"
              autocomplete="off"
              placeholder="请输入电话号码"
            ></el-input>
          </el-form-item>  
          <el-form-item label="树龄" prop="number" :rules="number">
            <el-input
              type="number"
              v-model.number="numberValidateForm.number"
              autocomplete="off"
              placeholder="请输入树龄"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="submitForm('numberValidateForm')"
              >提交</el-button
            >
            <el-button @click="resetForm('numberValidateForm')">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>
  </div>
</template>
<script>
const cryptoJs = new CryptoJs()
export default {
  data () {
    let checkValue = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('值不能为空'))
      }
      setTimeout(() => {
        if (!Number.isInteger(value)) {
          callback(new Error('请输入数字值'))
        } else {
          if (value < 1) {
            callback(new Error('值必须大于1'))
          } else {
            callback()
          }
        }
      }, 200)
    }
    return {
      numberValidateForm: {
        name: '', // 姓名
        phone: '', // 电话
        number: null // 数量
      },
      name: { required: true, message: '姓名不能为空' },
      phone: { required: true, message: '联系电话不能为空' },
      number: [{ required: true, validator: checkValue, trigger: ['change', 'blur'] }]
    }
  },
  methods: {
    submitForm (formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          let params = this.numberValidateForm
         console.log('验证成功,参数为',params)
        } else {
            console.log('数据验证不成功')
          return false
        }
      })
    },
    //重置
    resetForm (formName) {
      this.$refs[formName].resetFields()
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>


最后自己在项目中所用代码 :

<template>
  <!-- 自定义校验规则 -->
  <div class="formBox">
    <!-- :model 绑定的一定要是一个 对象 numberValidateForm: {}
否则会报错 : 类型检查失败。应为对象,获取了值为 “” 的字符串 -->
    <el-form
      label-position="top"
      :model="numberValidateForm"
      ref="numberValidateForm"
      label-width="200px"
      class="demo-ruleForm"
    >
      <el-form-item size="mini">
        <!-- 文本类型输入框 -->
        <el-input
          v-if="item.quInputType === '1'"
          v-model="item.modelValue"
          type="textarea"
          :style="`width:${item.answerInputWidth}px`"
          :rows="item.answerInputRow"
          placeholder="请输入内容"
        ></el-input>
        <!-- 日期类型输入框 -->
        <el-date-picker
          v-if="item.quInputType === '2'"
          :readonly="true"
          v-model="item.dateValue"
          type="date"
          placeholder="请选择日期"
        ></el-date-picker>
        <!-- 数字类型输入框 -->
        <!-- prop 要跟 rules 规则里的名字对应一致 -->
        <el-form-item
          v-if="item.quInputType === '3'"
          prop="numValue"
          :rules="numValue"
        >
          <el-input
            size="small"
            autocomplete="off"
            type="numValue"
            v-model.number="item.numberValidateForm.numValue"
            :maxlength="item.numDigit"
            @input="handleNumInput('numberValidateForm')"
            placeholder="请输入数字"
          ></el-input>
        </el-form-item>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 在 item 中的数据字段
      numberValidateForm: {
        numValue: "", // 数字输入框的绑定值
      },
      quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
      modelValue: "", // 默认文本域绑定值
      answerInputWidth: "300", // input 宽度
      answerInputRow: "1", // input 高度
      dateValue: "", // 日期选择器绑定值
      numValue: [
        { required: true, message: "内容不能为空" },
        { type: "number", message: "内容必须为数字" },
      ],
      numValue: "", // 数字输入框绑定值
      numDigit: "1", // 控制数字位数
    };
  },
  methods: {
    handleNumInput(formName) {
      // 输入时实时校验
      /* 注意 : 这里有个大坑啊, 我的 this.$refs[formName]. 一直提示报错 : 不是一个函数
      通过打印才发现层级出现了点问题, 改成 this.$refs[formName][0] 就 OK 了
      也不知道是不是只有我的是如此 (如果你也出现了类似情况, 不妨就加上 [0] 试一试吧) */
      this.$refs[formName][0].validate((valid) => {
        if (valid) {
          let params = this.numberValidateForm;
          console.log("验证成功,参数为", params);
        } else {
          console.log("数据验证不成功");
          return false;
        }
      });
    },
  },
};
</script>
<style lang="scss" scoped>
</style>

后来呢 , 这种方法只是能给到一个提示作用 , 并不能阻止到用户继续输入非数字内容 , 

所以继续百度搜寻方法 ,=>  Vue 只能输入数字

不过呢这个有个问题就是使用的 v-bid:value  , 来控制的输入框输入内容 , 

所以无法再使用 v-model  来进行双向绑定了 (缺点)

<template>
  <div class="formBox">
    <el-form label-position="top" label-width="200px" class="demo-ruleForm">
      <el-form-item size="mini">
        <!-- 文本类型输入框 -->
        <el-input
          v-if="item.quInputType === '1'"
          v-model="item.modelValue"
          type="textarea"
          :style="`width:${item.answerInputWidth}px`"
          :rows="item.answerInputRow"
          placeholder="请输入内容"
        ></el-input>
        <!-- 日期类型输入框 -->
        <el-date-picker
          v-if="item.quInputType === '2'"
          :readonly="true"
          v-model="item.dateValue"
          type="date"
          placeholder="请选择日期"
        ></el-date-picker>
        <!-- 数字类型输入框 -->
        <!-- :value 导致 v-model 双向绑定失效 -->
        <!-- v-model.number="item.numValue" -->
        <el-input
          v-if="item.quInputType === '3'"
          size="small"
          :maxlength="item.numDigit"
          @input="handleNumInput"
          :value="inputNum"
          placeholder="请输入数字"
        ></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 在 item 中的数据字段
      numValue: "", // 数字输入框的绑定值
      quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
      modelValue: "", // 默认文本域绑定值
      answerInputWidth: "300", // input 宽度
      answerInputRow: "1", // input 高度
      dateValue: "", // 日期选择器绑定值
      numValue: "", // 数字输入框绑定值
      numDigit: "1", // 控制数字位数
      oldInputNum: "" /* 数字类型输入框初始值 */,
    };
  },
  computed: {
    inputNum() {
      return this.oldInputNum;
    },
  },
  methods: {
    handleNumInput(event) {
      /* 此方法因为使用了 v-bind:value , 所以原本的 v-model 双向绑定就不能使用了 , 
      否则此方法会不生效 , 因此就需要我们自己去获取到用户最后输入的值了 */
      // 缺点就是没有了双向绑定的便利性了
      // let val = event.target.value.trim();
      let val = event.trim();
      // 只能是正整数或空,可根据需求修改正则
      // item = e.target.value.replace(/[^\d]/g,'')
      if (/^[1-9]\d*$|^$/.test(val)) {
        this.oldInputNum = val;
      } else {
        // event.target.value = this.oldInputNum;
        event = this.oldInputNum;
      }
    },
  },
};
</script>
<style lang="scss" scoped>
</style>

最后使用了老项目里的代码方法 , 直接在 输入框上写 oninput

    <el-input
      oninput="this.value=this.value.replace(/\D/g,'')"
      onafterpaste="this.value=this.value.replace(/\D/g,'')"
    ></el-input>

但是此方法不知为何 , 用户在输入完一些数字之后 , 再输入汉字时 , 可能会将所输入的数字删除掉 , 可能是正则的 replace 导致的 , 因此这还可能会影响到 v-model 的正常取值

只能通过获取用户最后一次输入的值赋值给 v-model 绑定的值了

<template>
  <div>
    <!-- 数字类型输入框 -->
    <el-input
      v-if="item.quInputType === '3'"
      size="small"
      :maxlength="item.numDigit"
      v-model.number="item.numValue"
      oninput="this.value=this.value.replace(/\D/g,'')"
      @change="handleNumInput($event, item)"
      placeholder="请输入数字"
    ></el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 在 item 中的数据字段
      numValue: "", // 数字输入框的绑定值
      quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
      modelValue: "", // 默认文本域绑定值
      answerInputWidth: "300", // input 宽度
      answerInputRow: "1", // input 高度
      dateValue: "", // 日期选择器绑定值
      numValue: "", // 数字输入框绑定值
      numDigit: "1", // 控制数字位数
    };
  },
  methods: {
    handleNumInput(event, item) {
      // 为了防止 v-model 失效 , 只好将最后一次输入的值赋值给绑定值了
      item.numValue = event;
    },
  },
};
</script>

<style lang="scss" scoped>
</style>
举报

相关推荐

0 条评论