VUE3封装复杂校验样式组件

221 阅读1分钟

样式

image.png

子组件代码

<template>
  <div class="special-validate el-form--item" :class="!isValidated ? 'is-error': '' ">
    <el-input
      v-model="value"
      placeholder="Please enter"
      :disabled="isDisabled"
      @focus="()=>{validateInfo.isShow = true}"
      @blur="()=>{validateInfo.isShow = false}"
      @input="handleInput(value)"
    />
    <div class="validate-meesage" v-if="validateInfo.isShow" :show-message="false">
      <div v-for="(item) in validateInfo.info" :key="item.message">
        <div class="validate-info-box">
          <span class="icon-box"><svg-icon :name="item.icon" style="width: 12px;height: 12px"></svg-icon></span>
          <span class="message-box" :class="item.icon==='fail'?'fail-message':''">{{ item.message }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/13cf9c496d0747969ddba8e8c3eb6ef6~tplv-k3u1fbpfcp-watermark.image?)
<script>
import { defineComponent, reactive, ref } from "vue";

export default defineComponent({
  name: "mutiValidateInput",
  props: {
    validateInfoList: {
      type: Array,
      default: () => [],
      required: true
    },
    isDisabled: {
      type: Boolean,
      default: false
    }
  },
  setup(props, context) {
    let isValidated = ref(true);
    const infoList = props.validateInfoList;
    const validateInfo = reactive({
      isShow: false,
      info: []
    });
    infoList.forEach(item => {
      const { message, rule } = item;
      validateInfo.info.push({ message, rule, icon: "warning" });
    });
    const handleInput = (value) => {
      context.emit("update:value", value);
      let validateRes = false;
      validateInfo.info.forEach(validate => {
        const rule = validate.rule;
        let isValidated = false;
        if (Object.prototype.toString.call(rule) === "[object RegExp]") {
          isValidated = rule.test(value);
        } else if (typeof rule === "function") {
          isValidated = rule(value);
        }
        validate.icon = isValidated ? "success" : "fail";
      });
      validateRes = validateInfo.info.every(item => item.icon === "success");
      isValidated = validateRes;
      return validateRes;
    };
    return {
      isValidated,
      validateInfo,
      handleInput
    };
  }
});
</script>

<style scoped lang="scss">
.special-validate {
  position: relative;
  width: 100%;

  .validate-meesage {
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
    width: 300px;
    background-color: #fff;
    box-shadow: 0px 2px 10px 0px rgba(37, 54, 109, 0.12);
    border: 1px solid #E9ECF5;
    padding: 12px;
    padding-bottom: 4px;
    border-radius: 8px;
    font-size: 11px;
    color: #4C4E5A;

    &:before {
      content: '';
      position: absolute;
      border-left: 6px solid transparent;
      border-top: 6px solid transparent;
      border-bottom: 6px solid transparent;
      border-right: 6px solid #fff;
      left: -12px;
      top: 51%;
      transform: translateY(-50%);
    }

    &:after {
      content: '';
      display: block;
      position: absolute;
      width: 7px;
      height: 7px;
      border: 1px solid #E9ECF5;
      border-top: none;
      border-right: none;
      left: -8px;
      top: 50%;
      transform: rotate(45deg) translateY(-50%);
    }

    .validate-info-box {
      line-height: 16px;
      margin-bottom: 8px;
      display: flex;

      .icon-box {
        padding-top: 2px;
        margin-right: 8px;
      }

      .message-box.fail-message {
        color: #FC4646;
      }
    }
  }
}
</style>

父组件使用

<el-form-item label="Catalog ID" prop="catalogId" class="required-sign">
  <muti-validate-input
    v-model:value="obj.catalogId"
    :is-disabled="text === 'Edit Catalog'"
    :validate-info-list="validateIdInfoList">
  </muti-validate-input>
</el-form-item>