React中通过tree组件实现不确定层级的折叠菜单效果
1、实现效果
- 折叠菜单的层级可以不相同、可以无限层级,具体根据读取的数据库数据为依据
- 菜单内容读取数据库获得
- 具体效果如下
- 折叠菜单是否可以继续召开取决于前面是否有可召开图标,如下图所示
2、实现原理
- 初始化加载页面并未获取全部层级的数据,只是第一层级
- 如果有子层级则呈现可展开图标,可进一步加载呈现下一层级菜单内容,否则没有
- 是否可继续加载呈现下一层级,原理同上
3、代码实现分步解析
(1)第一步:依赖组件
- 本效果的实现主要是依赖于antd组件库中的Tree组件
- 所以在项目中需要引入该组件,代码如下
import { Tree} from "antd"; const TreeNode = Tree.TreeNode;
(2)第二步:在状态机中设置用于存放初始化加载以及子层级菜单的数据内容
// 状态机 constructor(props, context) { super(props, context); this.state = { treeData: [], //存放初始化加载的菜单内容,即第一层级菜单内容 TreeNodeData: [], //存放获取的子菜单内容 } }(3)第三步:折叠菜单Tree控件的呈现
renderTreeNodes(data) { return data.map((item) => { if (item.children) { return ( <TreeNode title={item.title} key={item.key} dataRef={item}> {this.renderTreeNodes(item.children)} </TreeNode> ); } return <TreeNode {...item} title={item.title} dataRef={item} />; }); } render() { return ( <Layout> <Layout style={{ padding: "10px 0", background: "#fff" }}> <Sider width={300} style={{ background: "#fff", paddingLeft: "15px" }}> <Tree loadData={this.onLoadData} defaultSelectedKeys="0" > {this.renderTreeNodes(this.state.treeData)} </Tree> </Sider> </Layout> </Layout> ); }
(4)第四步:初始化加载第一层级菜单内容
- 利用componentWillMount周期函数,在初始化加载页面时进行网络请求,获取第一层级菜单数据
componentWillMount() { const subject_name = "数学"; const grade = "初中"; this.getKnowledgeStorageFirstLayer(grade, subject_name); //获取第一层级菜单内容 } // 获取第一层层级关系 getKnowledgeStorageFirstLayer(grade, subject_name) { let ajaxTimeOut=$.ajax({ url: "/api_v1.1/knowledge/getKnowledgeStorager", type: "GET", dataType: "json", data: { "grade": grade, "subject": subject_name }, timeout:2000, success: function (data) { if (data.errorCode == 0) { console.log("成功获取第一层层级关系"); console.log(data); this.setState({ treeData: data.msg });//将第一层级数据赋值给状态机 } else { console.log("暂无数据"); } }.bind(this), error: function (xhr, status, err) { }.bind(this), complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数 if (status == "timeout") {//超时,status还有success,error等值的情况 ajaxTimeOut.abort(); //取消请求 this.time_out() } } }); }(5)第五步:单击可展开图标,进行网络请求获取下一层级菜单内容
onLoadData = (treeNode) => { return new Promise((resolve) => { if (treeNode.props.children) { resolve(); return; } this.getKnowledgeStorageNextLayer(treeNode.props.knowid); setTimeout(() => { treeNode.props.dataRef.children = this.state.TreeNodeData; this.setState({ treeData: [...this.state.treeData], }); resolve(); }, 1000); }); } // 通过id获取下一层层级关系 getKnowledgeStorageNextLayer(knowid) { return new Promise((resolve) => { let ajaxTimeOut= $.ajax({ url: "/api_v1.1/knowledge/getKageNextLayer", type: "GET", dataType: "json", data: { "knowid": knowid }, timeout:2000, success: function (data) { if (data.errorCode == 1) { console.log("没有下一层结构"); } else { console.log("成功获取下一层极结构"); console.log(data); this.setState({ TreeNodeData: data.msg }); //将下一层级菜单内容赋值给状态机 } }.bind(this), error: function (xhr, status, err) { }.bind(this), complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数 if (status == "timeout") {//超时,status还有success,error等值的情况 ajaxTimeOut.abort(); //取消请求 } } }); }) }
4、整体代码
import React, { Component } from "react"; import $ from "jquery"; import "../../../style_css/antd.css"; import { Layout, Tree, Row, Col } from "antd"; const { Header, Content, Footer, Sider } = Layout; const TreeNode = Tree.TreeNode; class KnowledgeRepository_List_Slider extends Component { // 状态机 constructor(props, context) { super(props, context); this.state = { treeData: [], //存放初始化加载的菜单内容,即第一层级菜单内容 TreeNodeData: [], //存放获取的子菜单内容 } } // 通过id获取第一层层级关系 getKnowledgeStorageFirstLayer(grade, subject_name) { let ajaxTimeOut=$.ajax({ url: "/api_v1.1/knowledge/getKnowledgeStorageFirstLayer", type: "GET", dataType: "json", data: { "grade": grade, "subject": subject_name }, timeout:2000, success: function (data) { if (data.errorCode == 0) { console.log("成功获取第一层层级关系"); console.log(data); this.setState({ treeData: data.msg });//将第一层级数据赋值给状态机 } else { console.log("暂无数据"); } }.bind(this), error: function (xhr, status, err) { }.bind(this), complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数 if (status == "timeout") {//超时,status还有success,error等值的情况 ajaxTimeOut.abort(); //取消请求 console.log("网络不稳定"); } } }); } // 通过id获取下一层层级关系 getKnowledgeStorageNextLayer(knowid) { return new Promise((resolve) => { let ajaxTimeOut= $.ajax({ url: "/api_v1.1/knowledge/getKnowledgeStorageNextLayer", type: "GET", dataType: "json", data: { "knowid": knowid }, timeout:2000, success: function (data) { if (data.errorCode == 1) { console.log("没有下一层结构"); } else { console.log("成功获取下一层极结构"); console.log(data); this.setState({ TreeNodeData: data.msg }); //将下一层级菜单内容赋值给状态机 } }.bind(this), error: function (xhr, status, err) { }.bind(this), complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数 if (status == "timeout") {//超时,status还有success,error等值的情况 ajaxTimeOut.abort(); //取消请求 console.log("网络不稳定"); } } }); }) } onLoadData = (treeNode) => { return new Promise((resolve) => { if (treeNode.props.children) { resolve(); return; } this.getKnowledgeStorageNextLayer(treeNode.props.knowid); setTimeout(() => { treeNode.props.dataRef.children = this.state.TreeNodeData; this.setState({ treeData: [...this.state.treeData], }); resolve(); }, 1000); }); } renderTreeNodes(data) { return data.map((item) => { if (item.children) { return ( <TreeNode title={item.title} key={item.key} dataRef={item}> {this.renderTreeNodes(item.children)} </TreeNode> ); } return <TreeNode {...item} title={item.title} dataRef={item} />; }); } componentWillMount() { const subject_name = "数学"; const grade = "初中"; this.getKnowledgeStorageFirstLayer(grade, subject_name); //获取第一层级菜单内容 } render() { return ( <Layout> <Layout style={{ padding: "10px 0", background: "#fff" }}> <Sider width={300} style={{ background: "#fff", paddingLeft: "15px" }}> <Tree loadData={this.onLoadData} defaultSelectedKeys="0" > {this.renderTreeNodes(this.state.treeData)} </Tree> </Sider> </Layout> </Layout> ); } } export default KnowledgeRepository_List_Slider;
5、特别说明
- 由于此效果的实现依赖的是Tree控件,有些字段名称必须使用该控件是别的名字,如获取网络数据时,菜单名字必须使用title字段,是否包含子层级使用isLeaf字段(true:无;false:有)
- 具体请参考网址:https://ant.design/components/tree-cn/
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。