不使用函数式组件改造Ant Design Vue递归子菜单

Vue.js 组件提供了一个 functional 开关,设置为 true 后,就可以让组件变为无状态、无实例的函数化组件。因为只是函数,所以渲染的开销相对来说较小。

在对使用Ant Design Vue项目的左侧菜单国际化改造时,由于翻译函数$t是挂载在Vue实例上的,而子菜单是通过函数化组件(functional template)递归生成,因此需要将子菜单改成非函数化组件实现。

函数化组件实现

官方给出的demo是这样的:single-file-recursive-menu-单文件递归菜单

Github上讨论的相关issue:使用SubMenu报错Cannot read property ‘isRootMenu’ of undefined"

<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>
<script>
export default {
  props: ['menuInfo'],
};
</script>

这种方式需要menuInfo在传入前已经被处理为需要的数据,如果子菜单无需处理数据,则可以满足需求,也有更好的渲染速度。

不使用函数化组件实现

当需要调用实例上的方法,则需要改造为非函数化实现,如果只是单纯的去掉functionalprops则会报错Cannot read property ‘isRootMenu’ of undefined"

查阅相关资料,发现是需要自行传递组件参数,因此导入Menu组件,将组件参数填充至自定义的subMenu组件,并通过v-bind="$props"传递,最终改造如下:

<template>
  <a-sub-menu :key="menuInfo.key" v-bind="$props" v-on="$listeners">
    <span slot="title">
      <a-icon v-show="menuInfo.icon" :type="menuInfo.icon" />
      <span>{{ menuInfo.title }}</span>
    </span>
    <template v-for="item in menuInfo.child">
      <a-menu-item v-if="!item.child || (item.child && item.child.length === 0)" :key="item.menuId" :fullPath="item.urlAddr" :menuId="item.menuId">
        <a-icon v-show="item.icon" :type="item.icon" />
        <span>{{ item.menuName }}</span>
      </a-menu-item>
      <sub-menu v-else :key="item.menuId" :menu-info="item" v-on="$listeners" />
    </template>
  </a-sub-menu>
</template>
<script>
  import { Menu } from 'ant-design-vue'
  export default {
    name: "subMenu",
    isSubMenu: true,
    props: {
      ...Menu.SubMenu.props,
      menuInfo: {
        type: Object
      }
    }
  }
</script>

此时非函数式子菜单改造完成,可以使用实例上的相关方法或自行定义相关内容了。

参考文章

发布者

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注