牛骨文教育服务平台(让学习变的简单)
博文笔记

React中通过tree组件实现不确定层级的折叠菜单效果

创建时间:2018-03-20 投稿人: 浏览次数:296

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/

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。