ant-design-vue-pro icon indicating copy to clipboard operation
ant-design-vue-pro copied to clipboard

在使用ant-design-vue的menu组件将路由映射成菜单时,菜单渲染不出来,浏览器报错TypeError: Invalid attempt to spread non-iterable instance

Open blateyang opened this issue 4 years ago • 1 comments

Question (问题描述) 我仿照着极客时间Vue开发实战36课唐金洲老师的讲课试图根据路由渲染菜单,但菜单渲染不出来,浏览器报错TypeError: Invalid attempt to spread non-iterable instance,具体出错点是在Array.forEach ()方法上(见下面SiderMenu.vue中的注释)。

我已与geektime分支[email protected]的代码比对过,并未发现有什么大的问题,浏览器断点调试有发现getMenuData函数中的this为undefined, 返回的menuData有数组元素,如下 menuData: Array(2) 0: {path: "/dashboard", name: "dashboard", meta: {…}, component: {…}, children: undefined} 1: {path: "/form", name: "form", meta: {…}, component: {…}, children: undefined} 希望有人能帮忙解决我遇到的问题!

Describe the solution you'd like (你期待的是什么?) A clear and concise description of what you want to happen. 期待能够根据路由正常渲染出菜单 Additional context(附加信息) Add any other context or screenshots about the feature request here. 下面是我相关的代码:

  1. router/index.js中的路由配置
const routes = [
  {
    path: "/user",
    name: "user",
    hideInMenu: true,
//    component: {render: h=>h("router-view")}, // 将当前组件渲染到router-view中
    component: () =>
        import(/* webpackChunkName: "user" */ "../Layouts/UserLayout.vue"),
    children: [
      {
        path: "/user",
        redirect: "/user/login"
      },
      {
        path: "/user/login",
        name: "login",
        component: () =>
        import(/* webpackChunkName: "user" */ "../views/user/Login.vue")
      },
      {
        path: "/user/register",
        name: "register",
        component: () =>
        import(/* webpackChunkName: "user" */ "../views/user/Register.vue")
      }
    ]
  },
  {
    path: "/",
//    component: {render: h=>h("router-view")}, // 将当前组件渲染到router-view中
    component: () =>
        import(/* webpackChunkName: "user" */ "../Layouts/BasicLayout.vue"),
    children: [
      {
        path: "/",
        redirect: "/dashboard/analysis"
      },
      {
        path: "/dashboard",
        name: "dashboard",
        meta: {title: "仪表盘", icon: "dashboard"},
        component: {render: h=>h("router-view")},
        children: [
          {
            path: "/dashboard/analysis",
            name: "analysis",
            meta: {title:"分析页"},
            component: () =>
            import(/* webpackChunkName: "about" */ "../views/Dashboard/Analysis.vue")
          }
        ]
      },
        // form
        {
          path: "/form",
          name: "form",
          meta: {title: "表单", icon: "form"},
          component: { render: h => h("router-view") },
          children: [
            {
              path: "/form/basic-form",
              name: "basicform",
              meta: {title: "基本表单"},
              component: () =>
                import(/* webpackChunkName: "form" */ "../views/Forms/BasicForm")
            },
            {
              path: "/form/step-form",
              name: "stepform",
              meta: {title: "分步表单"},
              hideChildrenInMenu: true,
              component: () =>
                import(/* webpackChunkName: "form" */ "../views/Forms/StepForm"),
              children: [
                {
                  path: "/form/step-form",
                  redirect: "/form/step-form/info"
                },
                {
                  path: "/form/step-form/info",
                  name: "info",
                  component: () =>
                    import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step1")
                },
                {
                  path: "/form/step-form/confirm",
                  name: "confirm",
                  component: () =>
                    import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step2")
                },
                {
                  path: "/form/step-form/result",
                  name: "result",
                  component: () =>
                    import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step3")
                }
              ]
            }
          ]
        }
    ]
  },
  {
    path: "*",
    name: "404",
    hideInMenu: true,
    component: NotFound,
  }
];
  1. SiderMenu.vue
<template>
  <div style="width: 200px">
    <a-menu
      :default-selected-keys="['1']"
      :default-open-keys="['2']"
      mode="inline"
      :theme="navTheme"
      :inline-collapsed="collapsed"
    >
      <template v-for="item in menuData">
        <a-menu-item v-if="!item.children" :key="item.path">
          <a-icon v-if="item.meta.icon" type="item.meta.icon" />
          <span>{{ item.meta.title }}</span>
        </a-menu-item>
        <sub-menu v-else :key="item.path" :menu-info="item"/>
      </template>
    </a-menu>
  </div>
</template>

<script>
import SubMenu from "../Layouts/SubMenu.vue"
export default {
  components: {
    'sub-menu': SubMenu,
  },
  data() {
    const menuData = this.getMenuData(this.$router.options.routes)
    return {
      collapsed: false,
      list: [],
      menuData,
    };
  },
  props: {
      navTheme: {
        type: String,
        default: "dark",
      }
  },
  methods: {
    toggleCollapsed() {
      this.collapsed = !this.collapsed;
    },
    getMenuData(routes=[]) {
      const menuData = []
      routes.forEach(item=>{ // 在此处报错
        if(item.name && !item.hideInMenu) {
          const newItem = {...item}
          delete newItem.children
          if(item.children && !item.hideChildrenInMenu) { 
            newItem.children = this.getMenuData(item.children) 
          }else{
            this.getMenuData(item.children)
          }
          menuData.push(newItem)
        }else if(!item.hideInMenu && !item.hideChildrenInMenu && item.children) {
          menuData.push(...this.getMenuData(item.children)) 
        }
        return menuData
      })
    }
  },
};
</script>

blateyang avatar Feb 07 '21 15:02 blateyang

@tangjinzhou 请唐老师有空能否帮我看一下

blateyang avatar Feb 12 '21 07:02 blateyang