封装组件库-表单(4)
2023, Mar 07
实现表单的封装
基于Element-plus框架的Form表单组件进行封装。
实现的功能
- 实现配置型表单,通过json对象的方式自动生成表单
- 具备更加完备的功能,表单验证,动态删减表单,集成第三方插件(富文本编辑器)
- 用法更简单,扩展性强(配置项形式),可维护
- 能够进行弹框嵌套表单等多场景。
初始配置
- 注册路由组件form,配置为Container组件的子路由组件
- 采用路由懒加载,箭头函数异步引入组件。
- 注册通用组件from,为路由组件的子组件,以便组件间通信。
- 将通用组件form注册为全局组件
实现富文本编辑器的集成
- 为了扩展表单的功能,将WangEditor编辑器集成到表单组件中
- 类型定义
export interface FormOptions {
type: 'editor'
}
- 父组件配置表单数据
let options: FormOptions[] =[
{
type: 'editor',
value: '',
prop: 'desc',
label: '描述',
placeholder: '请输入描述',
rule:[
{
required: true,
message: '描述不能为空',
trigger: 'blur'
}
]
}
]
- 子组件:单独处理富文本编辑器组件。
<el-form-item :prop="item.prop" :label="item.label"
v-if="!item.children || !item.children.length">
<component
v-if="item.type !== 'upload' && item.type !== 'editor'"
v-bind="item.attrs"
:is="`el-${item.type}`"
v-model="model[item.prop]"
:placeholder="item.placeholder">
</component>
<el-upload >
</el-upload>
<!-- 富文本编辑器 -->
<div v-if="item.type === 'editor'" id="editor" style="width:100%"></div>
</el-form-item>
<!-- 在初始化表单时,对富文本编辑器进行初始化 -->
let initForm = ()=>{
if(props.options && props.options.length) {
let m: any = {}
let r: any = {}
props.options.map((item: FormOptions)=>{
m[item.prop] = item.value
r[item.prop!] = item.rule as any
//初始化富文本
if(item.type === 'editor'){
//操作dom元素,用nextTick,获取editor,设置placeholder,创建富文本编辑器
nextTick(()=>{
if(document.getElementById('editor')){
const editor = new E('#editor')
editor.config.placeholder = item.placeholder!
editor.create()
//初始化富文本的内容,改变输入框内容,desc描述不变,并没有改变表单值,调用onchange
editor.txt.html(item.value)
editor.config.onchange = function (newHtml: string) {
model.value[item.prop!] = newHtml
};
edit.value = editor
}
})
}
})
model.value = cloneDeep(m)
rules.value = cloneDeep(r)
}
}
表单组件的提交与重置的实现
- 子组件:在el-form组件里设置一个action插槽,给el-form设置ref,同时从插槽里将表单和数据给父组件。form表单实例的类型官网没有提供,在源码里找到接口类型。
<el-form ref='form' :model="model">
<el-form-item>
<slot name="action" :form="form" :model="model"></slot>
</el-form-item>
</el-form>
- 父组件
<!-- 作用域插槽,含提交和重置按钮 -->
<template #action="scoped">
<el-button type="primary" @click="submitForm(scoped)">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</template>
<!-- 作用域插槽接收实例的接口类型 -->
interface Scoped{
form: FormInstance,
model: any
}
<!-- 提交 -->
let submitForm = (scoped: Scoped)=>{
//表单验证是否通过,ELMessage组件提示
scoped.form.validate(valid=>{
if(valid){
console.log(scoped.model);
ElMessage.success('提交成功!')
}else{
ElMessage.error('表单填写有误,请重试!')
}
})
}
<!-- 重置表单,因为集成了富文本,所以要重写重置方法 -->
let resetForm = ()=>{
form.value.resetFields()
}
- 子组件重写resetFields方法,vue3的ref无法将方法传递出去,使用提出的defineExpose将方法分发出去
//重写重置表单的方法
let resetFields = ()=>{
//重置element-plus表单
form.value!.resetFields()
//重置富文本编辑器的内容
//获取到富文本的配置项
if(props.options && props.options.length){
let editorItem = props.options.find(item=>item.type==='editor')!
//赋值为富文本的初始值
edit.value.txt.html(editorItem.value)
}
}
//分发方法
defineExpose({
resetFields
})