点击异步获取数据并且处理成树形数据的组件

这是一个基于顺序表和树的数据结构,点击时异步获取数据,再点击即收起来,再点击时由于数据已经有了,直接展开,结合顺序遍历和递归遍历的树形组件。附上完整代码,如有疑问,可留言。

随便附上一个不规则树递归检索代码

/**
 * 不规则树递归检索
 */
getTreeNodeById(id, trees) {
    for (let tree of trees) {
        if(tree.Id === id) {
            return tree;
        } else {
            if(tree.Next.length > 0) {
                return this.getTreeNodeById(id, tree.Next);
            }
        }
    }
    return {};
}

效果图:

LayoutAside.vue

<template>
    <div class="page-container-aside">
        <div class="page-container-aside-head">
            <a class="edit-mail" href="/edit-mail" target="_blank">写邮件</a>
        </div>
        <div class="line"></div>
        <div class="page-container-aside-body">
            <div class="emails">
                <tree
                    v-for="tree in trees"
                    :key="tree"
                    :treeList="tree"
                >
                </tree>
            </div>
            <div class="line"></div>
            <ul class="functions">
                <li
                    v-for="funItem in mailFunList"
                    :key="funItem.id"
                >
                    <a
                        v-if="funItem.target === '_blank'"
                        :href="funItem.url"
                        :target="funItem.target"
                    >
                        {
   
   { funItem.text }}
                    </a>
                    <router-link
                        v-else
                        :to="funItem.url"
                    >
                        {
   
   { funItem.text }}
                    </router-link>
                </li>
            </ul>
        </div>
    </div>
</template>

<script>
    /**
     * 邮箱功能
     */
    let mailFunList = [
        {
            id: 1,
            text: '信息收集',
            url: 'https://b5.office.cmbchina.com/InfoCol/Default.aspx',
            target: '_blank'
        },{
            id: 2,
            text: '个人模板',
            url: '/setting/personal-template'
        },{
            id: 3,
            text: '邮箱设置',
            url: '/setting'
        },{
            id: 4,
            text: '邮件备份',
            url: 'http://99.3.14.178/MailBackupSvc',
            target: '_blank'
        },{
            id: 5,
            text: '邮箱管理',
            url: 'https://office.cmbchina.com/mailrpt/Default.aspx',
            target: '_blank'
        },{
            id: 6,
            text: '问题反馈',
            url: '/edit-mail',
            target: '_blank'
        }
    ]

    import tree from '@/components/Tree.vue';

    export default{
        name: 'LayoutAside',
        components: {
            'tree': tree
        },
        data () {
            return {
                trees: [],
                mailFunList: mailFunList
            }
        },
        methods: {
            /**
             * 获取最初根结点的邮箱文件夹集合
             */
            getOriginMailBoxList() {
                this.$api.mailSetApi.getFolderById(
                    {id: '0'},
                    (data) => {
                        let folders = [];// 最初根结点的邮箱文件夹
                        for (let node of data) {
                            // 处理数据
                            let newNode = {
                                "id": node.id,
                                "name": node.name,
                                "hasChild": node.children,
                                "type": node.id,
                                "isOpen": false,
                                "next":  []
                            };
                            folders.push(newNode);
                        }
                        this.trees = folders;
                    },
                    () => {}
                );
            },
        },
        created() {
            /**
             * 获取最初根结点的邮箱文件夹集合
             */
            this.getOriginMailBoxList();
        }
    }
</script>

<style>
    /* 侧边栏初始化 */
    .page-container-aside{
        position: absolute;
        top: 0;
        left: 0;
        width: 170px;
        height: 100%;
        flex: 1;
    }
    .page-container-aside .page-container-aside-head{
        position: relative;
        text-align: center;
    }
    .page-container-aside .page-container-aside-body{
        position: relative;
        overflow-x: auto;
        overflow-y: auto;
        height: calc(100% - 55px);
    }
    /* / 侧边栏初始化 */

    /* 分隔线 */
    .page-container-aside .line{
        clear: both;
        border-top: solid #D8DEE5 1px;
    }
    /* / 分隔线 */

    /* 写邮件的按钮 */
    .page-container-aside .page-container-aside-head .edit-mail{
        display: inline-block;
        width: 100px;
        height: 35px;
        margin: 10px;
        border: 1px solid #aaa;
        border-radius: 5px;
        color: #000;
        line-height: 35px;
        cursor: pointer;
        font-size: 14px;
        text-decoration: none;
    }
    /* / 写邮件的按钮 */

    /* emails */
    .page-container-aside .page-container-aside-body .emails{
        /* width: 170px; */
        /* overflow-x: auto; */
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li{
        position: relative;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li i {
        display: inline-block;
        position: absolute;
        top: 4px;
        width: 15px;
        height: 15px;
        margin: 0px 5px 0 10px;
        border-radius: 4px;
        border: solid 1px #bbb;
        --gradient-start: #c1c1c1;
        --gradient-start-text: #c1c1c1;
        --gradient-end: #FAF8F9;
        --gradient-end-text: '#FAF8F9';
        background: linear-gradient(33deg, var(--gradient-start), var(--gradient-end));
        cursor: pointer;
        color: #646464;
        font-size: 14px;
        line-height: 14px;
        font-style: normal;
        text-align: center;
        -moz-user-select:none;/*文字取消选中 - 火狐*/
        -webkit-user-select:none;/*文字取消选中 - webkit浏览器*/
        -ms-user-select:none;/*文字取消选中 - IE10*/
        -khtml-user-select:none;/*文字取消选中 - 早期浏览器*/
        user-select:none;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li span {
        display: inline-block;
        position: relative;
        top: 1px;
        width: 120px;
        padding: 2px 5px;
        transition: all ease .1s;
        -moz-user-select:none;/*文字取消选中 - 火狐*/
        -webkit-user-select:none;/*文字取消选中 - webkit浏览器*/
        -ms-user-select:none;/*文字取消选中 - IE10*/
        -khtml-user-select:none;/*文字取消选中 - 早期浏览器*/
        user-select:none;
        color: #000;
        font-size: 14px;
        cursor: pointer;
        text-decoration: none;
        overflow: hidden;/*  单行文本显示省略号 */
        text-overflow:ellipsis;/*  单行文本显示省略号 */
        white-space: nowrap;/*  单行文本显示省略号 */
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul .tree-li > span {
        left: 35px;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li .tree-ul .tree-li > span {
        left: 35px;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li span:hover {
        color: #fff;
        background-color: #AAD4FF;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li .tree-ul .tree-li {
        padding-left: 28px;
    }
    .page-container-aside .page-container-aside-body .emails .tree-ul li span.active {
        color: #fff;
        background-color: #ff5f5f;
    }
    /* / emails */

    /* functions */
    .page-container-aside .page-container-aside-body .functions li{
        width: 100%;
        text-align: center;
    }
    .page-container-aside .page-container-aside-body .functions li a{
        display: block;
        width: 100%;
        height: 100%;
        color: #000;
        font-size: 14px;
        line-height: 30px;
        transition: all ease .3s;
        text-decoration: none;
        user-select: none;
    }
    .page-container-aside .page-container-aside-body .functions li a:hover{
        color: #fff;
        background-color: #AAD4FF;
    }
    /* / functions */
</style>

Tree.vue

<template>
    <div class="tree">
        <ul class="tree-ul">
            <li class="tree-li">
                <i
                    @click="toggle(mailTree)"
                    v-if="isFolder(mailTree)"
                >
                    {
   
   { mailTree.isOpen ? '-' : '+' }}
                </i>

                <span
                    :class="setClass(mailTree)"
                    :title="mailTree.name"
                    @click.stop="routerGo(mailTree)"
                >
                    {
   
   { mailTree.name }}
                </span>
                <tree
                    v-for="item in mailTree.next"
                    :treeList="item"
                    :key="item"
                    v-show="mailTree.isOpen"
                >
                </tree>
            </li>
        </ul>
    </div>
</template>

<script>
    export default {
        name: 'tree',
        props: ['treeList'],
        data() {
            return{
            }
        },
        computed: {
            /**
             * 当前选中的文件夹ID
             */
            curentFolderId: function() {
                // console.log(this.$store.state.to);
                let currentRoute = this.$store.state.to;
                if (currentRoute.name !== 'mailList') {
                    if(currentRoute.name === 'home') {
                        return "1";
                    }
                    return '';
                }
                // console.log(currentRoute.params);
                return (currentRoute.params !== undefined) && (currentRoute.params.fid !== undefined)
                ?
                (
                    // console.log(this.$store.state.to.params.Id),
                    currentRoute.params.fid
                )
                :
                (
                    // console.log(this.$store.state.to),
                    "1"
                )
            },
            /**
             * 监听树
             */
            mailTree() {
                return this.treeList;
            }
        },
        methods: {
            /**
             * 判断是否为文件夹
             */
            isFolder(mailTree) {
                return mailTree.hasChild;
            },
            /**
             * 点击设置文件夹激活样式
             */
            setClass(mailTree) {
                return {
                    active: this.curentFolderId == mailTree.id
                }
            },
            /**
             * 文件夹打开与关闭
             */
            toggle(mailTree) {
                // 判断是否已打开
                if(mailTree.isOpen === true) {
                    mailTree.isOpen = !mailTree.isOpen;
                } else {
                    // 判断是否有子集合
                    if(mailTree.hasChild) {
                        //判断子集合是否已经加载
                        if(mailTree.next.length > 0) {
                            mailTree.isOpen = !mailTree.isOpen;
                        } else {
                            try {
                                this.getMailBoxListById(mailTree);
                                mailTree.isOpen = !mailTree.isOpen;
                            } catch (error) {
                                alert("获取数据失败 =>", error);
                            }
                        }
                    }
                }
            },
            /**
             * 点击跳转文件夹路由
             */
            routerGo(mailTree) {
                this.$router.push ({
                    name: 'mailList',
                    params: {
                        fid: mailTree.id,
                        Name: mailTree.name,
                        folderType: mailTree.type,
                        r: new Date().getTime()
                    }
                });
            },
            /**
             * 根据Id获取下一层级的邮箱文件夹集合
             */
            getMailBoxListById(mailTree) {
                this.$api.mailSetApi.getFolderById(
                    {id: mailTree.id},
                    (data) => {
                        let next = [];// 下一层的邮箱文件夹
                        for (let node of data) {
                            // 处理数据
                            let newNode = {
                                "id": node.id,
                                "name": node.name,
                                "hasChild": node.children,
                                "type": mailTree.type,// 继承最初父级结点的type
                                "isOpen": false,
                                "next":  []
                            };
                            next.push(newNode);
                        }
                        mailTree.next = next;
                    },
                    () => {}
                );
            },
            /**
             * 不规则树递归检索
             */
            // getTreeNodeById(id, trees) {
            //     for (let tree of trees) {
            //         if(tree.Id === id) {
            //             return tree;
            //         } else {
            //             if(tree.Next.length > 0) {
            //                 return this.getTreeNodeById(id, tree.Next);
            //             }
            //         }
            //     }
            //     return {};
            // }
        },
    }
</script>

猜你喜欢

转载自blog.csdn.net/Cai181191/article/details/113842457