json生成表单主要是解决一些业务上的烦恼,可以用json来描述一个表单组件,话不多说 上代码
//首先思考 json怎么来描述一个表单
//首先 表单控件应该有一个名字 input button select等等
//这里我们就描述了一个input的控件
let obj = {
type:'input'
}
//然后光渲染没用 我们需要给他加上布局 双向绑定 监听事件 然后绑定字段 传给后台做交互 引申一下 把这//个对象可以扩展一下
obj={
type: 'input',//是什么控件
name: 'cccc',//字段是什么
value: '',//双向绑定的值
label: '2222',//在表单里面他的label
props: { //需要传递下去的props
placeholder: '11111',
},
col: { //布局
span: 4,
},
on:{ //事件监听
change:(v:any)=>{
console.log(v)
}
}
}
//这样经过我们的处理 应该就描述了一个input组件 但是实际应用中 你应该需要一次描述多个 那他的数据格
//式就应该是
//const rule = [{...obj},{这里继续描述下一个}]
//描述完了 怎么渲染呢 看文档!!!! https://www.vue3js.cn/docs/zh/guide/render-function.html
复制代码
//那我们就应该是
{vm.rule.map((i: IRuleItem) => {
return (
<a-col span={i.col?.span}>
<a-form-item label={i.label}>{vm.getRuleItem(i)}</a-form-item>
</a-col>
;
})}
复制代码
基本上到这个地方 组件的模型就已经出来了 但是他也基本上不能满足需求 只是一辆玩具车 怎么来拓展我们的功能呢?怎么让他支持自定义组件呢 看文档!!!
同理可证 我们的自定义组件 可以通过模仿vue.compoent的注册来实现
//插件代码
import { Component } from 'vue';
import { Vue } from 'vue-class-component';
import CForm from './corsrc/CForm';
interface Iplu {
install: any
component: (name: string, component: Component) => void
newComponent: { [x: string]: Component; }
// testArr:{}
}
interface IPluVue extends Vue {
[x: string]: any
}
const plu: Iplu = {
install(Vue: IPluVue, op: any) {
Vue.component('CForm', CForm);
},
component(name: string, component: Component) {
//这个就是模拟的组件注册 每次都是渲染的vnode 同时利用{} 的 key-value的结构特点 来储存他
this.newComponent[name] = component;
},
newComponent: {},
};
export default plu;
复制代码
/**
上面说了自定义组件的实现 但是如果是基本的表单功能 我还要一个一个去注册吗?太麻烦了吧 我门不是应该解决麻烦吗 然后我要去找答案 怎么找? 看文档!!!
*/
复制代码
//这里提到了一个api resolveComponent(string) 返回一个已经注册组件 那不就万事大吉了
//也就是说 el-input a-input会被渲染成组件 而不是html标签
//同理可证 我们可以在这个插件里面 写上一些默认的 常用的form组件 我用antd 就是
interface defaultCompoentObj {
input: string
datePicker: string
[x: string]: any
}
const index: defaultCompoentObj = {
input: 'aInput',
datePicker: 'aDatePicker',
};
export default index;
复制代码
这个就是实现了 默认组件还有一些自定义组件的渲染还有注册的功能 但是这个时候 他只是一个雏形 依然还是玩具车
//看到上面的代码很多大佬 就会明白 下拉框 不是一个json能描述的了的 而是 需要select option来配合的
//怎么办? 自己写啊 自己用的你的ui库去封装一个下拉 然后放到默认的表单组件里面
interface defaultCompoentObj {
input: string
datePicker: string
[x: string]: any
}
import select from '@/form/corsrc/CForm';
const index: defaultCompoentObj = {
input: 'aInput',
datePicker: 'aDatePicker',
select,
};
export default index;
//vnode和全局注册的组件都是可以找到的 这样就解决了一些不方便的问题 小伙伴们 不就可以拿去二次开发了吗
复制代码
上完整代码 我是用的antd做的二次开发
import { defineComponent, h, reactive, VNode, resolveComponent } from 'vue';
import { Vue } from 'vue-class-component';
import { IRuleItem } from '../types/ruleType';
import { setDefaultCompoent, setRuleItemColSapn } from '@/form/utils/utils';
interface CForm extends Vue {
rule: []
formModel: { [x: string]: any; }
getRuleItem: (i: IRuleItem) => VNode
returnFormModel: () => void
}
const CForm = defineComponent({
name: 'CForm',
props: {
rule: {
type: Array,
default: () => {
return [];
},
},
value: {
type: Object,
default: () => {
return {};
},
},
},
setup(props, ctx) {
const formModel: CForm['formModel'] = reactive({});
//Api func 这里用一下方法处理 数据
const funcObj = {
getValue: (key: string) => { //根据Key获取函数
return formModel[key];
},
getFormData: () => { //获取表单数据 主要是用作提交
return formModel;
},
};
const CApi = reactive(props.value);
CApi.getValue = funcObj.getValue;
CApi.getFormData = funcObj.getFormData;
ctx.emit('update:valie', CApi);
/**
* 根据rule的item来生成组件
* @param i
* @returns
*/
if (props.rule.length) {
const rule: IRuleItem[] = props.rule as IRuleItem[];
rule.forEach((i: IRuleItem) => {
formModel[i.name] = i.value;
});
}
function getRuleItem(i: IRuleItem) {
return h(resolveComponent(setDefaultCompoent(i.type)), {
value: formModel[i.name],
...i.props,
...i.on,
'onUpdate:value': (v: any) => {
formModel[i.name] = v;
},
});
}
return {
formModel,
getRuleItem,
};
},
/**
*
* @param vm :model="formState" :label-col="labelCol" :wrapper-col="wrapperCol"
* @returns
*/
render(vm: CForm) {
// setRuleItemColSapn(i.col?.span)
return (
<div class="CForm">
<a-form model={vm.formModel}>
<a-row>
{vm.rule.map((i: IRuleItem) => {
return (
<a-col span={i.col?.span}>
<a-form-item label={i.label}>{vm.getRuleItem(i)}</a-form-item>
</a-col>
);
})}
</a-row>
</a-form>
</div>
);
},
});
export default CForm;
复制代码
另外有vue3一起学习的小伙伴也可以喊我 我学不动了 求指教 有啥好的解决方法也可以喊我一起 我感觉我写的好丑
主要是只是提供一个思路 抽象一下日常的业务组件 用数据去描述 解决问题
源码地址 还有自定义组件的判断没有实现 应该是在2021年7月10日之前完成
github.com/q969210177/…
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END