需求:我们要实现如下格式的树结构,能动态创建、删除和输入值并能回显数据。
步骤一:通过iview UI 组件生成一个树结构,只要data里面的数据是数组且内部每一个对象里都嵌套一个 children 数组,就能创建一个树结构。
<Tree style="margin-top:20px;" :data="information" :render="renderContent" ></Tree>
数据结构如下:
步骤二:render 函数结构如下, 在methods定义里面。
renderContent(h,{ root, node, data }){
return h("div",{
style: {
display: 'inline-block',
width: '100%'
}
},[
h("span","菜单参数"), // 显示的标题
h("Input",{ // 输入框
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入变量名",
value:data.variableName // 回显数据
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.variableName = e.target.value // 将输入的值赋值到data的参数里
console.log("输出输入的值:",e.target.value)
}
}
}),
h("Input",{
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入字段名",
value:data.fieldName // 回显值
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.fieldName = e.target.value // 输入时赋值
console.log("输出输入的值:",e.target.value)
}
}
}),
h("Checkbox",{ // 复选框
props:{
size: 'small',
level:{ required: true }, // 必填项
value:data.isRequired == "1" ? true:false // 回显值,1为true不是则为false。
},
style:{
width:"70px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.isRequired = e // 输入时赋值
console.log("输出输入的值:",e)
}
}
},"是否必传"), // 复选框旁的提示文字。
h("Input",{
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入类型名",
value:data.type // 回显数据
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.type = e.target.value // 输入时赋值
console.log("输出输入的值:",e.target.value)
}
}
}),
h("Input",{
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入最大长度",
value:data.maxlength // 回显数据
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.maxlength = e.target.value // 输入时赋值
console.log("输出输入的值:",e.target.value)
}
}
}),
h("Input",{
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入示例值",
value:data.example // 回显数据
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.example = e.target.value // 输入时赋值
console.log("输出输入的值:",e.target.value)
}
}
}),
h("Input",{
props:{
size: 'small',
level:{ required: true } // 必填项
},
attrs:{
placeholder:"请输入描述",
value:data.description // 回显数据
},
style:{
width:"130px",
marginLeft: '20px'
},
on:{
'on-change':(e)=>{
data.description = e.target.value // 输入时赋值
console.log("输出输入的值:",e.target.value)
}
}
}),
h('Button', { // 在结尾添加按钮
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add',
type: 'success'
}),
style: {
marginLeft: '20px',
fontSize:'16px'
},
on: {
click: () => { this.append(data) } // data是点击时这一行的数据
}
}),
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-close',
type: 'error'
}),
style: {
marginLeft: '8px',
fontSize:'16px'
},
on: {
click: () => { this.remove(root, node, data) } // data是点击时这一行的数据
}
})
])
},
步骤三:结构出来后,我们就需要实现动态添加父级和子集,由于官方文档给出的解释太过笼统,下面我们将一步一步实现此结构。
步骤四:首先点击新增参数按钮,生成父级级和子级结构。
①通过工厂函数生成一个对象,此对象包含了树结构内部的所有参数,用来生成父级和子级。
studentSystem(variableName,fieldName,isRequired,type,
maxlength,example,description,children,fieldId,fatherId,apiId){
let obj = {}
obj.variableName = variableName // 变量名
obj.fieldName = fieldName // 字段名称
obj.isRequired = isRequired // 是否必传
obj.type = type // 类型
obj.maxlength = maxlength // 最大长度
obj.example = example // 示例值
obj.description = description // 描述
obj.children = children // 子集数组
obj.fieldId = fieldId // 本身id
obj.parentId = fatherId // 父 id
obj.apiId = apiId // 接口id
obj.requestType = "1" // body
return obj
},
②点击新增参数按钮,使用上面创建的函数,往data绑定的数组里面添加一条对象。
newParameters(){
this.information.push(this.studentSystem("","","","","","","",
[],this.newID++,0,this.id1))
},
效果如下:
③:点击加号时,往当前点击的这一行对象里面的children数组里添加一条对象。
data是当前点击这一行的所有数据。
append(data){
data.children.push(this.studentSystem("","","","","","","",
[],this.newID++,data.fieldId,this.id1))
},
效果如下:
④点击减号时,能删除点击的这一行结构。 官方给出的方法只能删除子一级的,无法删除父级,我们要单独写方法来删除父级。
首先我们在数组里通过indexOf来查找点击的这一行数据是否在总数组里,查到后返回其下标并通过splice来删除这一行。
最后我们在try和catch来执行,当try里删除子集报错时,就说明删除的是父级,就会执行catch里面的方法。
remove(root, node, data){
try {
// 删除子集
const parentKey = root.find(e => e === node ).parent
const parent = root.find(e => e.nodeKey === parentKey).node
const index = parent.children.indexOf(data)
parent.children.splice(index,1)
}catch{
// 删除一集
this.information.splice(this.information.indexOf(data),1)
}
},
步骤五:发请求保存数据,直接将整个数据传递过去即可。
saveSubmit(){
new Promise((resolve,reject)=>{
Api.addedParameterTreeStructure(this.information).then(response=>{
this.$Message.success("提交成功!")
this.$router.push("interfaceManagement")
}).catch(error=>{
reject(error)
})
})
},
步骤六: 发请求回显数据,拿到的数据直接赋值到数组里即可,由于在步骤二中已经将数组中的参数赋值到value中去,这里就直接能回显数据。
bodyParameterDisplayed(){
let data = { apiId:this.id1 }
new Promise((resolve,reject)=>{
Api.bodyParameterTreeStructureDisplayed(data).then(response=>{
this.information = response.result.bodyList
}).catch(error=>{
reject(error)
})
})
}