ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue-element-admin layout组件解析【Sidebar】

2021-12-06 17:34:47  阅读:278  来源: 互联网

标签:vue return admin 路径 isExternal default import icon layout


> index.vue

<template>
<!-- 判断是否显示logo -->
  <div :class="{'has-logo':showLogo}">
    <!-- 判断是否隐藏侧边栏 -->
    <logo v-if="showLogo" :collapse="isCollapse" />
    <!-- 主侧边栏标签 -->
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <!--
        default-active:活动菜单颜色
        collapse:侧边栏隐藏
        background-color: 背景颜色
        text-color:菜单中文本颜色
        unique-opened: 是否唯一打开
        active-text-colo: 活动文本颜色
        collapse-transition: 隐藏过渡
        mode="vertical":绑定变量
       -->
      <el-menu
        :default-active="activeMenu"
        :collapse="isCollapse"
        :background-color="variables.menuBg"
        :text-color="variables.menuText"
        :unique-opened="false"
        :active-text-color="variables.menuActiveText"
        :collapse-transition="false"
        mode="vertical"
      >
        <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
      </el-menu>
    </el-scrollbar>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'

export default {
  components: { SidebarItem, Logo },
  computed: {
    // 获取vuex中getter中的属性的值
    ...mapGetters([
      'permission_routes',
      'sidebar'
    ]),
    // 活动菜单
    activeMenu() {
      // 获取当前路由对象
      const route = this.$route
      // 获取meta对象 和路径对象
      const { meta, path } = route
      // 如果设置路径,侧边栏将突出显示您设置的路径
      if (meta.activeMenu) {
        return meta.activeMenu
      }
      return path
    },
    // 显示logo
    showLogo() {
      return this.$store.state.settings.sidebarLogo
    },
    // scss颜色变量
    variables() {
      return variables
    },
    // 是否关闭侧边栏
    isCollapse() {
      return !this.sidebar.opened
    }
  }
}
</script>

> Item.vue

<script>
export default {
  name: 'MenuItem',
  functional: true,
  props: {
    // 图标
    icon: {
      type: String,
      default: ''
    },
    // 标题头
    title: {
      type: String,
      default: ''
    }
  },
  render(h, context) {
    // 获取参数对象
    const { icon, title } = context.props
    const vnodes = []

    if (icon) {
      // 判断图标是否element-ui中的图标
      if (icon.includes('el-icon')) {
        // 使用i标签添加图标
        vnodes.push(<i class={[icon, 'sub-el-icon']} />)
      } else {
        // 不是element-ui直接添加外部icon路径
        vnodes.push(<svg-icon icon-class={icon}/>)
      }
    }
    // 判断是否存在标题头
    if (title) {
      // 添加标题头
      vnodes.push(<span slot='title'>{(title)}</span>)
    }
    // 返回拼接后的数组标签
    return vnodes
  }
}
</script>

<style scoped>
.sub-el-icon {
  color: currentColor;
  width: 1em;
  height: 1em;
}
</style>

> SidebarItem.vue

<template>
  <div v-if="!item.hidden">
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

<script>
import path from 'path' // 导入路径
import { isExternal } from '@/utils/validate' // 用于判断是外部的路径
import Item from './Item' // 迭代icon与title
import AppLink from './Link' // 应用关联 用于切换外部链接显示方法
import FixiOSBug from './FixiOSBug' // 用于修复IOS设备鼠标离开bug

export default {
  name: 'SidebarItem',
  components: { Item, AppLink },
  mixins: [FixiOSBug],
  props: {
    // route object 路由对象
    item: {
      type: Object,
      required: true
    },
    // 是否嵌套
    isNest: {
      type: Boolean,
      default: false
    },
    // 基本路径
    basePath: {
      type: String,
      default: ''
    }
  },
  data() {
    // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
    // TODO: 渲染函数重构
    this.onlyOneChild = null
    return {}
  },
  methods: {
    // 有一个子路由
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          // 临时设置(如果只有一个子路显示子路由并使用)
          this.onlyOneChild = item
          return true
        }
      })

      // 当只有一个子路由器时,默认显示子路由器
      if (showingChildren.length === 1) {
        return true
      }

      // 如果没有要显示的子路由器,则显示父级
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    // 解析路径
    resolvePath(routePath) {
      // 判断是否是外部的路径
      if (isExternal(routePath)) {
        return routePath
      }
      if (isExternal(this.basePath)) {
        return this.basePath
      }
      // 返回当前也解析好的路径
      return path.resolve(this.basePath, routePath)
    }
  }
}
</script>

> Link.vue

<template>
  <!-- is指定这个component渲染成为指定的标签类型  -->
  <!-- 绑定链接地址 -->
  <component :is="type" v-bind="linkProps(to)">
    <slot />
  </component>
</template>

<script>
import { isExternal } from '@/utils/validate' // 判断是否是外部path

export default {
  props: {
    to: {
      type: String,
      required: true
    }
  },
  computed: {
    // 判断是否是外部路径https
    isExternal() {
      return isExternal(this.to)
    },
    type() {
      // 是外部HTTPS返回a标签
      if (this.isExternal) {
        return 'a'
      }
      // 是本地路径返回一个router-link,它最终会被渲染成一个a标签
      return 'router-link'
    }
  },
  methods: {
    // 链接方法
    linkProps(to) {
      // 判断是否是外部HTTPS路径
      if (this.isExternal) {
        return {
          // 链接地址
          href: to,
          target: '_blank',
          rel: 'noopener'
        }
      }
      // 不是外部路径直接返回
      return {
        to: to
      }
    }
  }
}
</script>

> FixiOSBug.js

export default {
  computed: {
    // 获取应用设备
    device() {
      return this.$store.state.app.device
    }
  },
  mounted() {
    // In order to fix the click on menu on the ios device will trigger the mouseleave bug
    // 为了修复ios设备上点击菜单会触发鼠标离开的bug
    // https://github.com/PanJiaChen/vue-element-admin/issues/1135
    this.fixBugIniOS()
  },
  methods: {
    // 修复IOSbug函数
    fixBugIniOS() {
      // 获取子菜单对象
      const $subMenu = this.$refs.subMenu
      if ($subMenu) {
        // 处理鼠标离开
        const handleMouseleave = $subMenu.handleMouseleave
        $subMenu.handleMouseleave = (e) => {
          if (this.device === 'mobile') {
            return
          }
          handleMouseleave(e)
        }
      }
    }
  }
}

标签:vue,return,admin,路径,isExternal,default,import,icon,layout
来源: https://blog.csdn.net/weixin_50513383/article/details/121751501

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有