element-ui 组件库 el-form 实现

如果使用过 element-ui 组件库的人都知道,Form 表单由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据。用法如下:

<template>
  <el-form :model="form" :rules="rules" ref="form">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input v-model="form.password"></el-input>
    </el-form-item>
    <el-form-item>
      <button @click="validate">确认提交</button>
    </el-form-item>
  </el-form>
</template>
<script>
import Form from "./components/ElForm.vue";
import FormItem from "./components/ElFormItem.vue";
import Input from "./components/ElInput.vue";
export default {
  components: {
    "el-form": Form,
    "el-form-item": FormItem,
    "el-input": Input,
  },
  data() {
    return {
      form: {
        username: "",
        password: "",
      },
      rules: {
        username: [{ required: true, message: "请输入用户名" }],
        password: [{ required: true, message: "请输入密码" }],
      },
    };
  },
  methods: {
    validate() {
      // form组件中校验是通过
      this.$refs.form.validate((valid) => {
        if (valid) {
          alert("校验通过");
        } else {
          alert("校验不通过");
        }
      });
    },
  },
};
</script>

今天讲解 el-form,el-form-item,el-input 的基本实现原理。掌握 el-form 组件的设计思想。

你将学会组件之间的数据通信,eventBus、children、provide。

el-form 组件

<template>
  <form onsubmit="return false">
    <slot></slot>
  </form>
</template>
<script>
export default {
  provide() {
    return {
      form: this,
    };
  },
  props: {
    model: {
      type: Object,
    },
    rules: {
      type: Object,
    },
  },
  methods: {
    // 在form组件中检查所有的formItem是否全部通过校验
    validate(cb) {
      cb(this.$children.every((child) => child.validateStatus !== "error"));
    },
  },
};
</script>

el-form-item 组件

<template>
  <div>
    <label v-if="label">{{ label }}</label>
    <slot></slot>
    <!-- 有错误 显示错误提示信息 -->
    <div v-if="validateStatus === 'error'">
      {{ validateContent }}
    </div>
  </div>
</template>
<script>
import Vue from "vue";
Vue.prototype.$bus = new Vue();
export default {
  props: {
    label: String,
    prop: String,
  },
  inject: ["form"], // 注入父级的实例
  data() {
    return {
      validateStatus: "", // 当前表单是否通过校验
      validateContent: "", // 当前校验后的信息
    };
  },
  methods: {
    validate(value) {
      let rules = this.form.rules[this.prop]; // 获取当前对应的规则
      rules.forEach((rule) => {
        // 如果必填 并且没有值,那就出错
        if (rule.required && !value) {
          this.validateStatus = "error";
          this.validateContent = rule.message;
        } else {
          this.validateStatus = "";
          this.validateContent = "";
        }
      });
    },
  },
  mounted() {
    this.$bus.$on("input", (data) => {
      if (this._uid === data.id) {
        // 说明更改的是当前自己的输入框
        this.validate(data.value);
      }
    });
  },
};
</script>

el-input 组件

<template>
  <input type="text" :value="inputValue" @input="handleInput" />
</template>
<script>
export default {
  props: {
    value: String,
  },
  data() {
    return { inputValue: this.value };
  },
  methods: {
    handleInput(e) {
      // 更新数据
      this.inputValue = e.target.value;
      this.$bus.$emit("input", {
        id: this.$parent && this.$parent._uid, // 为了标识是哪个输入框
        value: this.inputValue,
      }); // 发射输入事件
    },
  },
};
</script>

表单校验这里也只是简单的判断,但是 Element 官网使用的是第三方的 npm 包。更多高级用法可参考 async-validator。

上面演示的代码是 vue2 版本,vue3 已经不在提供 eventBus 了,没有 $on 这个 API 了,推荐使用第三方的 npm 包 mitt 编写,源码也是这样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值