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" ="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 编写,源码也是这样的。
评论