最近项目提了一个需求,要求根据后端返回的数据在表单里展示各种类型的组件,包括但不限于输入框、单选按钮、表格...简而言之,后端传的数据里,就是会出现对象嵌套对象的数据,嵌套多少层是未知的o(╥﹏╥)o 下面的代码是经过一次次的迭代产生的.
父组件:
{{ item.annotation }}
1.headerData.external是要渲染的表单结构,是数组类型的数据,结构如下:
[{ "name": "attr1",// 属性的英文名称,一般用于获取对应数据或者是el-form-item绑定的prop "type": "string",// 此处可能是c++数据类型或者js数据类型亦或者是自定义类型等等,满足开发需要即可 "annotation": "属性1",// 属性的中文名称,一般用于展示,用于el-form-item绑定的label "isArray": 0 // 用来决定是否以表格展示 }, { "name": "wqrwe", "type": "scwrefer",// 自定义类型 "annotation": "某某", "isArray": 0, "children": [{ "name": "tyi", "type": "double", "annotation": "不知道", "isArray": 0 }, { "name": "ytuiyt", "type": "double", "annotation": "不知道", "isArray": 0 }, { "name": "ewrtgwer", "type": "double", "annotation": "不知道", "isArray": 0 }],// 可能会出现表单嵌套表单,在数据上体现就是对象嵌套 }]
递归组件:
HTML代码:
是
否
添加
js代码:
// 判断右侧信息面板属性类型来决定组件类型
componentsByType(temp) {
let obj = { compType: "", inputType: "" };
// dataType是声明的一个对象,里面是描述的前后端数据对应关系,比如说后端的int对应前端的number等
switch (dataType[temp.type]) {
case "number":
obj.compType = "input";
obj.inputType = "number";
break;
case "boolean":
obj.compType = "radio";
break;
case "string":
case "undefined":
case "null":
obj.compType = "input";
obj.inputType = "string";
break;
default:
obj.compType = undefined;
}
return obj;
},
// 往数组里添加一条数据 push进去
addBase(item) {
// ...
this.$forceUpdate();
},
// 删除数组的一条数据 使用splice
deleteBase(item, index) {
arr.splice(index, 1);
},
非基本类型数组组件:
添加
js代码:
// 添加一条记录
addData() {
let obj = {};
// 递归方法为数组添加一条数据,避免表格内嵌套的是多层结构
this.dealAttr(this.headerData, obj).then((res) => {
this.formValue[this.headerData.name].push(res);
this.$forceUpdate();
});
},
// 处理属性
dealAttr(attr, data) {
if (attr.children) {
for (let ele of attr.children) {
if (!ele.children) {
if (this.componentsByType(ele) == "string") {
this.$set(data, ele.name, ele.isArray == 1 ? [] : "");
this.$forceUpdate();
} else if (this.componentsByType(ele) == "number") {
this.$set(data, ele.name, ele.isArray == 1 ? [] : 0);
this.$forceUpdate();
}
} else {
if (ele.isArray == 1) {
this.$set(data, ele.name, []);
this.$forceUpdate();
} else {
this.$set(data, ele.name, {});
this.$forceUpdate();
this.dealAttr(ele, data[ele.name]);
}
}
}
}
return Promise.resolve(data);
},
// 删除一条记录
deleteData(name, index) {
this.formValue[name].splice(index, 1);
},
非基本类型表单组件:
代码没有全放,因为每个人碰到的需求可能都不一样,大概的逻辑都在。
本人接触前端两年,归来仍是菜鸟,这是我目前能想到的满足需求的方法,如果您有更好的想法,欢迎一起讨论~