靜態效果圖:
動態效果圖:
代碼(安裝ant design就可以跑了):
import { Checkbox, Collapse } from 'antd';
import React, { PureComponent } from 'react';
//假設這是後端返回的數據
const params = {
"authTree": [
{
"authName": "商場數據分析",
"authId": 1,
"children": [{
"authName": "數據概覽",
"authId": 3,
"children": [
{ "authName": "今日客流", "authId": 6 },
{ "authName": "整體趨勢", "authId": 7 }
]
},
{
"authName": "數據概覽2",
"authId": 4,
"children": [
{ "authName": "今日客流2", "authId": 8 },
{ "authName": "整體趨勢2", "authId": 9 }
]
}]
},
{
"authName": "商場數據分析2",
"authId": 2,
"children": [{
"authName": "數據概覽3",
"authId": 5,
"children": [
{ "authName": "今日客流3", "authId": 10 },
{ "authName": "整體趨勢3", "authId": 11 }
]
}]
}
],
"checkedList": [6, 7, 11]
}
class AuthoritySettingComponent extends PureComponent {
constructor(props) {
super(props);
this.state = {
authTree: [],
checkedList: [],
};
this.itemHandle = this.itemHandle.bind(this);
}
componentDidMount() {
// 後端返回的數據,轉成前端要用的數據保存頁面使用
const authTree = params.authTree;
const checkedList = params.checkedList;
this.setState({
authTree,
checkedList,
}, () => {
this.authTreeFun();
});
}
// 轉成前端要用的數據
authTreeFun() {
const checkedList = this.state.checkedList;
checkedList.forEach((item) => {
this.itemHandle(item);
});
}
// 代碼三級聯動核心就在這裏
itemHandle(authId, checked = true) {
const authTree = [...this.state.authTree];
authTree.forEach((item1) => {
if (item1.authId === authId) {
item1.checked = checked;
if (item1.children) {
item1.children.forEach((item2) => {
item2.checked = checked;
if (item2.children) {
item2.children.forEach((item3) => {
item3.checked = checked;
});
}
});
}
} else {
// 反向思路: 保存子選項框的個數, 子選項選中就-1, 等於0說明都選中了, 父選項就勾上
let temp1 = item1.children.length;
item1.children.forEach((item2) => {
if (item2.authId === authId) {
item2.checked = checked;
if (item2.children) {
item2.children.forEach((item3) => {
item3.checked = checked;
});
}
} else {
let temp2 = item2.children.length;
item2.children.forEach((item3) => {
if (item3.authId === authId) {
item3.checked = checked;
}
item3.checked ? temp2 -= 1 : temp2;
});
temp2 === 0 ? item2.checked = true : item2.checked = false;
}
// 選中-1, 未選中不動
item2.checked ? temp1 -= 1 : temp1;
});
// 長度是0, 父選項框就勾選
temp1 === 0 ? item1.checked = true : item1.checked = false;
}
});
this.setState({
authTree,
});
}
render() {
const { Panel } = Collapse;
const authTreeMap = this.state.authTree.map((item1) => (
// Panel是手風琴
<Panel
key={item1.authId}
header={(
<span onClick={(e) => { e.stopPropagation(); }}>
{/* 一級複選框(向下操控二級三級) */}
<Checkbox
name={item1.authId.toString()}
checked={item1.checked}
onClick={(e) => {
this.itemHandle(parseInt(e.target.name), e.target.checked);
}}
>
{item1.authName}
</Checkbox>
</span>
)}
>
{/* 二級複選框(向下操控三級,向上聯動一級) */}
{item1.children.map((item2) => (
<div key={item2.authId}>
<Checkbox
name={item2.authId.toString()}
checked={item2.checked}
onClick={(e) => {
this.itemHandle(parseInt(e.target.name), e.target.checked);
}}
>
{item2.authName}
</Checkbox>
<span>|</span>
{/* 三級複選框(向上聯動二級一級) */}
{item2.children.map((item3) => (
<Checkbox
key={item3.authId}
name={item3.authId.toString()}
checked={item3.checked}
onClick={(e) => {
this.itemHandle(parseInt(e.target.name), e.target.checked);
}}
>
{item3.authName}
</Checkbox>
))}
</div>
))}
</Panel>
));
return (
<div>
<Collapse expandIconPosition="right">
{authTreeMap}
</Collapse>
</div>
);
}
}
export default AuthoritySettingComponent;