• vue手写el-form组件


    index.vue

    <template>
      <div>
        <s-form :model="model" :rules="rules" ref="loginForm">
          <s-form-item label="用户名" prop="username">
            <s-input v-model="model.username"></s-input>
          </s-form-item>
          <s-form-item label="密码" prop="password">
            <s-input v-model="model.password" type="password"></s-input>
          </s-form-item>
          <s-form-item>
              <button @click="onLogin">登录</button>
          </s-form-item>
        </s-form>
        {{model}}
      </div>
    </template>
    
    <script>
    import SInput from "./SInput.vue";
    import SFormItem from "./SFormItem.vue";
    import SForm from "./SForm.vue";
    
    export default {
      components: {
        SInput,
        SFormItem,
        SForm
      },
      data() {
        return {
          model: {
            username: "tom",
            password: ""
          },
          rules: {
            username: [{ required: true, message: "用户名必填" }],
            password: [{ required: true, message: "密码必填" }]
          }
        };
      },
      methods: {
          onLogin() {
              this.$refs.loginForm.validate((isValid) => {
                  if (isValid) {
                      alert('登录!!!')
                  } else {
                      alert('有错!!')
                  }
              })
          }
      },
    };
    </script>
    
    

    SForm.vue

    <template>
      <div>
        <slot></slot>
      </div>
    </template>
    
    <script>
    export default {
      provide() {
        return {
          form: this // 传递Form实例给后代,比如FormItem用来校验
        };
      },
      props: {
        model: {
          type: Object,
          required: true
        },
        rules: {
          type: Object
        }
      },
      methods: {
        validate(cb) {
          // map结果是若干Promise数组
          const tasks = this.$children
            .filter(item => item.prop)
            .map(item => item.validate());
          //   所有任务必须全部成功才算校验通过
          Promise.all(tasks)
            .then(() => cb(true))
            .catch(() => cb(false));
        }
      }
    };
    </script>
    
    <style lang="scss" scoped>
    </style>
    

    SFormItem.vue

    <template>
      <div>
        <label v-if="label">{{label}}</label>
        <slot></slot>
        <!-- 校验信息 -->
        <p v-if="errorMessage">{{errorMessage}}</p>
      </div>
    </template>
    
    <script>
    import Schema from "async-validator";
    
    export default {
      data() {
        return {
          errorMessage: ""
        };
      },
      inject: ["form"],
      props: {
        label: {
          type: String,
          default: ""
        },
        prop: String
      },
      mounted() {
        // 监听校验事件、并执行监听
        this.$on("validate", () => {
          this.validate();
        });
      },
      methods: {
        validate() {
          // 执行组件校验
          // 1.获取校验规则
          const rules = this.form.rules[this.prop];
    
          // 2.获取数据
          const value = this.form.model[this.prop];
    
          // 3.执行校验
          const desc = {
            [this.prop]: rules
          };
          const schema = new Schema(desc);
          //   参数1是值,参数2是校验错误对象数组
        //   返回的Promise<boolean>
          return schema.validate({ [this.prop]: value }, errors => {
            if (errors) {
              // 有错
              this.errorMessage = errors[0].message;
            } else {
              // 没错,清除错误信息
              this.errorMessage = "";
            }
          });
        }
      }
    };
    </script>
    
    <style lang="scss" scoped>
    </style>
    

    SInput.vue

    <template>
        <div>
            <!-- 自定义组件要实现v-model必须实现:value, @input -->
            <!-- $attrs存储的是props之外的部分 -->
            <!-- {type:'password'} -->
            <input :value="value" @input="onInput" v-bind="$attrs">
        </div>
    </template>
    
    <script>
        export default {
            inheritAttrs: false, // 避免顶层容器继承属性
            props: {
                value: {
                    type: String,
                    default: ''
                }
            },
            methods: {
                onInput(e) {
                    // 通知父组件数值变化
                    this.$emit('input', e.target.value);
    
                    // 通知FormItem校验
                    this.$parent.$emit('validate');
                }
            },
        }
    </script>
    
    <style lang="scss" scoped>
    
    </style>
    
    请用今天的努力,让明天没有遗憾。
  • 相关阅读:
    Anaconda的安装和更新
    Python数据分析学习目录
    国标28181sip开源库介绍(陆续补充完备)
    开源sip server & sip client 和开发库 一览
    几种开源SIP协议栈对比
    用TCP穿透NAT(TCP打洞)的实现
    使用TCP协议的NAT穿透技术
    TCP点对点穿透探索--失败
    snmp++开发实例一
    socket跟TCP/IP 的关系,单台服务器上的并发TCP连接数可以有多少
  • 原文地址:https://www.cnblogs.com/cupid10/p/15121129.html
Copyright © 2020-2023  润新知