近期由于项目中的需要,在admin端使用到了iview中的树形控件,个人觉得用起来还不错,今天在这里分享一下,写得仓促,有部分地方未来得及优化, 有不足之处希望及时指正。
下面贴效果图:
代码部分:
1.首先是标签
<Tree :data="treeData" :render="renderContent" class="trees" empty-text="暂无分类..." @on-toggle-expand="toggleTree"/>复制代码
2.首次在created里面请求数据
created () {
this.getAllCategory();
},
data() {
return { deleteBoxShow: false,
createNodeShow: false,
nodeId: '',
nodeName: '',
nodeData: {},
nodeRoot: [],
nodeDetail: {},
treeNode: [],
pidWrap: [],
pid: '',
removeId: '',
}
},computed: {
treeData() {
const treeData = [
{
title: '图书分类',
expand: true,
render: (h, {root, node, data}) => {
return h('span',
{ //一级目录控制
style: {
display: 'inline-block',
width: '100%',
fontSize: '16px',
},
},
[
h('span', [
h('Icon', {
props: {
type: 'ios-folder-outline'
},
style: {
marginRight: '8px'
}
}),
h('span', data.title)
]),
h('span', {
style: {
display: 'inline-block',
float: 'right',
marginRight: '32px'
}
}, [h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add',
type: 'primary'
}),
style: {
width: '64px'
},
on: {
click: () => {
this.nodeName = '';
this.nodeData = data;
this.createNodeShow = true;
}
}
})
])
]);
},
children: this.treeNode
}
]
return treeData
}
},复制代码
3.解析后台返回data,并拼凑成自己需要的data
后台返回数据格式:
贴代码:
async getAllCategory(pid) { //首次pid默认为空,为-1,点击时传入pid
let isAlreadyRequest = this.pidWrap.indexOf(pid); //pidWrap为 [],防止相同的内容重复请求。
if (isAlreadyRequest === -1) {
this.pidWrap.push(pid)
} else {
return
}
const {treeNode} = this; //treeNode默认为 [],包含所有数据。
let rank = {
'num': 1, //等级 2/3/4
'pIndex': '',
'child': {
'index': '',
}
}
treeNode.filter((item, index) => {
if (item.id === pid) {
rank.num = 2;
rank.pIndex = index;
this.treeNode[index].children.filter((node, _index) => {
if (!node.id) {
this.treeNode[index].children.splice(_index, 1);
}
})
}
})
if (rank.num !== 2 && pid) {
treeNode.filter((item, index) => {
item.children.filter((node, _index) => {
if (node.id === pid) {
rank.pIndex = index;
rank.child.index = _index;
rank.num = 3;
node.children.splice(0,1)
}
})
})
}
if (pid && rank.num !== 2 && rank.num !== 3) {
rank.num = 4
}
//在api文件引入发送请求函数 --- export const reqGetCategory = (pid = -1) => ajax(`/api/category/v1/bookCategory/queryBookCategoryByPid?pid=${pid}`)
let allCategory = await reqGetCategory(pid);
if (allCategory.status === '0') {
if (!pid || rank.num === 1) {
allCategory.data.map(item => {
this.treeNode.push({
'title': item.name, 'id': item.id,
'children': [{}]
})
})
} else if (pid && rank.num === 2) {
let data = this.treeNode;
allCategory.data.map(item => {
this.treeNode[rank.pIndex].children.push({
'title': item.name,
'id': item.id,
'children': [{}]
})
})
} else if (pid && rank.num === 3) {
allCategory.data.map(item => {
this.treeNode[rank.pIndex].children[rank.child.index].children.push({
'title': item.name,
'id': item.id,
})
})
}
}
},//获取所有分类信息复制代码
4.树形控件渲染函数
toggleTree(data) {
this.getAllCategory(data.id);
},//点击伸缩箭头
renderContent(h, {root, node, data}) {
if (!node.node.title) return
return h('span', {
style: {
display: 'inline-block',
width: '100%',
fontSize: '15px',
position: 'relative'
},
}, [
h('span', [
h('Icon', {
props: {
type: 'ios-paper-outline'
},
style: {
marginRight: '8px',
},
}),
h('span', {
style: {
display: 'inline-block',
cursor: 'pointer',
height: '30px',
width: '50px',
lineHeight: '26px',
},
on: {
click: () => {
this.nodeId = node.node.id
}
}
}, data.title)
]),
h('span', {
style: {
display: 'inline-block',
float: 'right',
marginRight: '32px'
},
}, [
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add'
}),
style: {
marginRight: '8px'
},
on: {
click: () => {
this.pid = node.node.id
let key = node.nodeId;
if (node.parent === 0) {//二级
this.nodeName = '';
this.nodeData = data;
this.createNodeShow = true;
} else if (root[node.parent].parent === 0) {
this.nodeName = '';
this.nodeData = data;
this.createNodeShow = true;
} else {
return this.$Message.error('节点最高为四级!')
}
}
}
}),
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-remove'
}),
on: {
click: () => {
this.removeId = node.node.id
this.nodeData = data;
this.nodeRoot = root;
this.nodeDetail = node;
this.deleteBoxShow = true; //删除框
}
}
})
])
]);
},//渲染样式
async createNode() {
if (!this.nodeName) {
this.$Message.error('输入值不能为空!')
} else {
let {pid} = this;
let bookNode = await reqCreateSection(this.nodeName, "", "", pid ? pid : -1)
if (bookNode.status === '0') {
this.append(this.nodeData, bookNode.data);
this.$Message.success(bookNode.msg)
} else {
this.$Message.error(bookNode.msg)
}
}
},//新增节点
async removeNode() {
const {nodeRoot, nodeDetail, nodeData} = this;
let res = await reqDeleteCategory(this.removeId, 'bookCategory');
if (res.status === '0') {
this.remove(nodeRoot, nodeDetail, nodeData)
this.$Message.success(res.msg);
} else {
this.deleteBoxShow = false;
this.$Message.error(res.msg)
}
},
remove(root, node, data) {
const parentKey = root.find(el => el === node).parent;
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
parent.children.splice(index, 1);
this.deleteBoxShow = false;
},复制代码