element-ui 组件库 el-form 实现

共 3752字,需浏览 8分钟

 ·

2021-06-14 16:01


如果使用过 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 编写,源码也是这样的。


浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报