• Vue iview可收缩多级菜单的实现


    1. 递归组件实战

    views/layout.vue

    <template>
      <div class="layout-wrapper">
        <Layout class="layout-outer">
          <Sider collapsible v-model="collapsed" hide-trigger breakpoint="sm">
            <side-menu :collapsed="collapsed" :list="menuList"></side-menu>
          </Sider>
          <Layout>
            <Header class="header-wrapper">
              <Icon type="md-menu" :size="32" @click.native="handleCollapsed" :class="triggerClasses"/>
            </Header>
            <Content class="content-con">
              <Card shadow class="page-card">
                <router-view/>
              </Card>
            </Content>
          </Layout>
        </Layout>
      </div>
    </template>
    <script>
    import SideMenu from '_c/side-menu'
    export default {
      data () {
        return {
          collapsed: true,
          menuList: [
            {
              title: '111',
              name: 'menu1',
              icon: 'md-analytics'
            },
            {
              title: '222',
              name: 'menu2',
              icon: 'md-analytics'
            },
            {
              title: '333',
              name: 'menu3',
              icon: 'md-appstore',
              children: [
                {
                  title: '333-111',
                  name: 'menu31',
                  icon: 'md-apps'
                },
                {
                  title: '333-222',
                  name: 'menu32',
                  icon: 'md-apps',
                  children: [
                    {
                      title: '333-222-111',
                      name: 'menu321',
                      icon: 'ios-archive'
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      computed: {
        triggerClasses () {
          return ['trigger-icon', this.collapsed ? 'rotate' : '']
        }
      },
      components: {
        SideMenu
      },
      methods: {
        handleCollapsed () {
          this.collapsed = !this.collapsed
        }
      }
    }
    </script>
    <style lang="less" scoped>
    .layout-wrapper,
    .layout-outer {
      height: 100%;
      .header-wrapper {
        background: #fff;
        box-shadow: 0 1px 1px 1px rgba(0, 0, 0, 0.1);
        padding: 0 23px;
        .trigger-icon {
          cursor: pointer;
          transition: transform 0.3s ease;
          &.rotate {
            transform: rotateZ(-90deg);
            transition: transform 0.3s ease;
          }
        }
      }
      .content-con {
        padding: 10px;
        .page-card {
          min-height: ~"calc(100vh - 84px)";
        }
      }
    }
    </style>
    

    components/side-menu/index.js

    import SideMenu from './side-menu.vue'
    
    export default SideMenu
    

    components/side-menu/side-menu.vue

    <template>
      <div class="side-menu-wrapper">
        <slot></slot>
        <Menu width="auto" theme="dark" v-show="!collapsed" @on-select="handleSelect">
          <template v-for="item in list">
            <re-submenu
              v-if="item.children"
              :key="`menu_${item.name}`"
              :name="item.name"
              :parent="item"
            >
              <menu-item></menu-item>
            </re-submenu>
            <menu-item v-else :key="`menu_${item.name}`" :name="item.name">
              <Icon :type="item.icon"/>
              {{ item.title }}
            </menu-item>
          </template>
        </Menu>
        <div class="drop-wrapper" v-show="collapsed">
          <template v-for="item in list">
            <re-dropdown @on-select="handleSelect" v-if="item.children" icon-color="#fff" :show-title="false" :key="`drop_${item.name}`" :parent="item"></re-dropdown>
            <Tooltip v-else transfer :content="item.title" placement="right" :key="`drop_${item.name}`">
              <span @click="handleClick(item.name)" class="drop-menu-span">
                <Icon :type="item.icon" color="#fff" :size="30"/>
              </span>
            </Tooltip>
          </template>
        </div>
      </div>
    </template>
    <script>
    import ReSubmenu from './re-submenu'
    import ReDropdown from './re-dropdown'
    export default {
      name: 'SideMenu',
      components: {
        ReSubmenu,
        ReDropdown
      },
      props: {
        collapsed: {
          type: Boolean,
          default: false
        },
        list: {
          type: Array,
          default: () => []
        }
      },
      methods: {
        handleSelect (name) {
          console.log(name)
        },
        handleClick (name) {
          console.log(name)
        }
      }
    }
    </script>
    <style lang="less">
    .side-menu-wrapper {
      .ivu-tooltip,
      .drop-menu-span {
        display: block;
        width: 100%;
        text-align: center;
        padding: 10px 0;
      }
      .drop-wrapper > .ivu-dropdown {
        display: block;
        padding: 10px;
        margin: 0 auto;
      }
    }
    </style>
    
    • 不收缩
    • 在这里插入图片描述
    <template>
      <Submenu :name="parent.name">
        <template slot="title">
          <Icon :type="parent.icon" />
          {{ parent.title }}
        </template>
        <template v-for="item in parent.children">
            <re-submenu
              v-if="item.children"
              :key="`menu_${item.name}`"
              :name="item.name"
              :parent="item"
            >
            </re-submenu>
            <menu-item v-else :key="`menu_${item.name}`" :name="item.name">
              <Icon :type="item.icon" />
              {{ item.title }}
            </menu-item>
          </template>
      </Submenu>
    </template>
    
    <script>
    export default {
      name: 'ReSubmenu',
      props: {
        parent: {
          type: Object,
          default: () => ({})
        }
      }
    }
    </script>
    
    • 收缩
    • 在这里插入图片描述
    <template>
      <Dropdown @on-click="handleClick" placement="right-start">
        <span class="drop-menu-span" :style="titleStyle">
          <Icon :type="parent.icon" :color="iconColor" :size="30"></Icon>
          <span  color="#515a6e" v-if="showTitle">{{ parent.title }}</span>
        </span>
        <DropdownMenu slot="list">
          <template v-for="item in parent.children">
            <re-dropdown v-if="item.children" :key="`drop_${item.name}`" :parent="item"></re-dropdown>
            <DropdownItem v-else :key="`drop_${item.name}`" :name="item.name">
              <Icon :type="item.icon" color="#515a6e" :size="30"></Icon>
              {{ item.title }}
            </DropdownItem>
          </template>
        </DropdownMenu>
      </Dropdown>
    </template>
    
    <script>
    export default {
      name: 'ReDropdown',
      props: {
        parent: {
          type: Object,
          default: () => ({})
        },
        iconColor: {
          type: String,
          default: '#515a6e'
        },
        showTitle: {
          type: Boolean,
          default: true
        }
      },
      computed: {
        titleStyle () {
          return {
            textAlign: this.showTitle ? 'left' : 'center',
            paddingLeft: this.showTitle ? '16px' : ''
          }
        }
      },
      methods: {
        handleClick (name) {
          if (!this.showTitle) this.$emit('on-select', name)
        }
      }
    }
    </script>
    
  • 相关阅读:
    Flex随笔
    Flex中实现类似Javascript的confirm box
    正则表达式
    MySQL存储过程
    cvc-complex-type.2.4.a: Invalid content was found starting with element
    Spket在Eclipse/MyEclipse下的安装和配置(图文教程)
    关于安装linux时要怎么分区的考虑的參考方式?
    BZOJ 1975 SDOI2010 魔法猪学院 A*k短路
    使用scipy进行聚类
    Android 下拉刷新上拉载入效果功能
  • 原文地址:https://www.cnblogs.com/izhaong/p/12154278.html
Copyright © 2020-2023  润新知