• AntDesign vue学习笔记(五)导航菜单动态加载


    一、使用官方例子

    <template>
      <div style=" 256px">
        <a-button type="primary" @click="toggleCollapsed" style="margin-bottom: 16px">
          <a-icon :type="collapsed ? 'menu-unfold' : 'menu-fold'" />
        </a-button>
        <a-menu
          :defaultSelectedKeys="['1']"
          :defaultOpenKeys="['2']"
          mode="inline"
          theme="dark"
          :inlineCollapsed="collapsed"
        >
          <template v-for="item in list">
            <a-menu-item v-if="!item.children" :key="item.key">
              <a-icon type="pie-chart" />
              <span>{{ item.title }}</span>
            </a-menu-item>
            <sub-menu v-else :menu-info="item" :key="item.key" />
          </template>
        </a-menu>
      </div>
    </template>
    
    <script>
    // recommend use functional component
    // <template functional>
    //   <a-sub-menu :key="props.menuInfo.key">
    //     <span slot="title">
    //       <a-icon type="mail" /><span>{{ props.menuInfo.title }}</span>
    //     </span>
    //     <template v-for="item in props.menuInfo.children">
    //       <a-menu-item v-if="!item.children" :key="item.key">
    //         <a-icon type="pie-chart" />
    //         <span>{{ item.title }}</span>
    //       </a-menu-item>
    //       <sub-menu v-else :key="item.key" :menu-info="item" />
    //     </template>
    //   </a-sub-menu>
    // </template>
    // export default {
    //   props: ['menuInfo'],
    // };
    
    import { Menu } from 'ant-design-vue';
    const SubMenu = {
      template: `
          <a-sub-menu :key="menuInfo.key" v-bind="$props" v-on="$listeners">
            <span slot="title">
              <a-icon type="mail" /><span>{{ menuInfo.title }}</span>
            </span>
            <template v-for="item in menuInfo.children">
              <a-menu-item v-if="!item.children" :key="item.key">
                <a-icon type="pie-chart" />
                <span>{{ item.title }}</span>
              </a-menu-item>
              <sub-menu v-else :key="item.key" :menu-info="item" />
            </template>
          </a-sub-menu>
        `,
      name: 'SubMenu',
      // must add isSubMenu: true
      isSubMenu: true,
      props: {
        ...Menu.SubMenu.props,
        // Cannot overlap with properties within Menu.SubMenu.props
        menuInfo: {
          type: Object,
          default: () => ({}),
        },
      },
    };
    export default {
      components: {
        'sub-menu': SubMenu,
      },
      data() {
        return {
          collapsed: false,
          list: [
            {
              key: '1',
              title: 'Option 1',
            },
            {
              key: '2',
              title: 'Navigation 2',
              children: [
                {
                  key: '2.1',
                  title: 'Navigation 3',
                  children: [{ key: '2.1.1', title: 'Option 2.1.1' }],
                },
              ],
            },
          ],
        };
      },
      methods: {
        toggleCollapsed() {
          this.collapsed = !this.collapsed;
        },
      },
    };
    </script>

    增加@click事件

     

    点击弹出效果如下图,注意:这里@click后不能直接写@click="alert('a')",会报TypeError: _vm.alert is not a function

    二、其他实现方法

    一般的后台系统都有一个树形导航菜单,具体实现如下,主要参考
    https://my.oschina.net/u/4131669/blog/3048416

    menuList: [
            {
              'name': '首页',
              'url': 'http://192.168.1.100:9999',
              'iconType': 'laptop',
              'sidebars': []
            },
            {
              'name': '企业信息',
              'url': null,
              'iconType': 'bars',
              'sidebars': [
                {
                  'name': '公司管理',
                  'url': 'http://192.168.1.100:8890//swagger-ui.html',
                  'iconType': 'laptop',
                  'sidebars': []
                }
              ]
            },
            {
              'name': '工程管理',
              'url': 'http://192.168.1.100:9999/about',
              'iconType': 'laptop',
              'sidebars': []
            }
          ]
        }

    1、定义sub-menu组件,用于递归显示多级菜单

    <template functional>
      <a-sub-menu :key="props.menuInfo.name" >
        <span slot="title">
          <a-icon type="folder" />
          <span>{{ props.menuInfo.name +','+props.menuInfo.sidebars.length}}</span>
        </span>
        <template v-for="item in props.menuInfo.sidebars">
          <a-menu-item
            v-if="!item.sidebars.length"
            :key="item.key">
            <span>{{ item.name }}</span>
          </a-menu-item>
        </template>
      </a-sub-menu>
    </template>
    <script>
    export default {
      name: 'SubMenu',
      props: ['menuInfo']
    }

    不能在函数式组件里定义事件并通过@click掉用,但是可以调用父组件的事件,方法

    <template functional>
      <a-sub-menu :key="props.menuInfo.name" @click=parent.fetchMenu()>
    ...
    原因是:
    函数式组件没有实例,事件只能由父组件传递。

    template functional标志该组件为函数化组件

    2、在Mainfrm中引入组件

    import SubMenu from './SubMenu'
    components: {
    SubMenu
    }
    3、menu模板
    <template v-for="item in menuList">
      <a-menu-item v-if="!item.sidebars.length" :key="item.name">
         <a-icon :type="item.iconType" />
            <span>{{item.name}}</span>
      </a-menu-item>
      <sub-menu v-else :menu-info="item" :key="item.name"/>
    </template>

     6、最终实现效果如下

     

    地址:https://www.jianshu.com/p/c549c3d0f595这篇文章的递归方法点击事件显示是正常的,他这个用的是原生html元素,需要美化界面,代码如下

    list: [
    {
        "id": "1",
        "menuName": "项目管理",
        "childTree": [{
            "menuName": "项目进度",
            "childTree": [{
                "menuName": "项目一",
                "childTree": [{ "menuName": "详细信息" }]
            }]
        }, {
            "menuName": "任务安排"
        }]
    }, 
    {
        "id": "2",
        "menuName": "数据统计"
    }, 
    {
        "id": "3",
        "menuName": "人员管理"
    }]
    // 子组件代码
    <template>
        <li>
            <span @click="toggle">
                {{ model.menuName }}
            </span>
            <ul v-if="isFolder" v-show="open">
                <items v-for="(item, index) in model.childTree" :model="item" :key="index"></items>
            </ul>
        </li>
    </template>
    
    <script type="text/javascript">
        export default {
            // 组件递归必要条件,name属性
            name: 'items',
            props: ['model'],
            data() {
                return {
                    // 控制子列表的显示隐藏
                    open: false
                }
            },
            computed: {
                // 是否还有子列表需要渲染,作为v-if的判断条件
                isFolder() {
                    return this.model.childTree && this.model.childTree.length
                }
            },
            methods: {
                // 切换列表显示隐藏的方法
                toggle() {
                    if(this.isFolder) {
                        this.open = !this.open
                    }
                },
            }
        }
    </script>
    <template>
        <div>
            <ul>
                <items v-for="(model, index) in list" :model="model" :key="index"></items>
            </ul>
        </div>
    </template>
    
    <script type="text/javascript">
        components: {
            Items
        },
        data() {
            return {
                list: ...
            }
        }
    </script>
  • 相关阅读:
    【Flutter 实战】1.20版本更新及新增组件
    【Flutter 实战】各种各样形状的组件
    【Flutter 实战】全局点击空白处隐藏键盘
    Flutter —布局系统概述
    【Flutter 实战】17篇动画系列文章带你走进自定义动画
    lvs负载简介,原理,常见使用案例及Keepalived高可用
    02 . MongoDB复制集,分片集,备份与恢复
    Go之Casbin简介,安装,模型,存储,函数
    govendor包管理及Go项目热加载
    教你三招快速文件批量重命名方法
  • 原文地址:https://www.cnblogs.com/zhaogaojian/p/11101909.html
Copyright © 2020-2023  润新知