qq_24394075
2019-08-04 19:49 阅读 1.8k

vue项目如何使用render函数写一个类似组件模版的递归组件?

80

如下是我用emelent-ui组件写的一个导航组件。由于有多个子级菜单,这里使用了递归。
首先,父组件是如下这样的

<template>
  <el-menu
    background-color="#303133"
    text-color="#C0C4CC"
    active-text-color="#409EFF"
    class="el-menu"
    :collapse="true"
  >
  <navs :asideNav="asideNav"></navs>
  </el-menu>
</template>
<!--  :collapse="false" -->
<script>
import Navs from './components/Navs'
export default {
  name: 'AsideNav',
  components: {
    Navs
  },
  props: {
    asideNav: Array
  }
}
</script>

<style lang="stylus" scoped>
  .el-menu--collapse>div>.el-menu-item span, .el-menu--collapse>div>.el-submenu>.el-submenu__title span
    height: 0
    width: 0
    overflow: hidden
    visibility: hidden
    display: inline-block
  .el-menu--collapse>div>.el-menu-item .el-submenu__icon-arrow, .el-menu--collapse>div>.el-submenu>.el-submenu__title .el-submenu__icon-arrow
    display: none;
  .el-menu
    border: none
  .el-menu:not(.el-menu--collapse) {
    width: 200px
  }
  ul
    color: #fff
</style>

子组件是如下这样的

<template>
  <div>
    <el-submenu v-for="item of asideNav" :key="item.url" :index="item.url" v-if="item.son">
      <template slot="title">
        <i class="iconfont">{{item.icon}}</i>
        <span slot="title">{{item.name}}</span>
      </template>
      <navs :asideNav="item.son"></navs> // 递归自调用
    </el-submenu>
    <el-menu-item v-else :index="item.url">
      <i class="iconfont">{{item.icon}}</i>
      <span slot="title">{{item.name}}</span>
    </el-menu-item>
  </div>
</template>

<script>
import Navs from './Navs'
export default {
  name: 'Navs',
  components: {
    Navs
  },
  props: {
    asideNav: Array // 父组件传递过来的json数据
  }
}
</script>

<style lang="stylus" scoped>
</style>

以上代码实际上已经解决了我要实现的无限级导航的要求,但有一个小bug。我这样写完以后,由于子组件模版内的根元素必须有一个div,所以导致emelent-ui导航模版在收缩的时候会出现一点点小问题,以至于我必须得修改css才能修正bug。后来想到可以使用render函数来重写一个模版组件、但由于我技术不娴熟,练了两天,只懂个皮毛。写完以后各种报错。
如下是我用我勤劳的小双手写的带错误的render函数模版

export default {
  props: {
    myData: Array
  },
  render(createElement) {
    let data = this.myData
    let ret = []

    return data.map(item => {
      if (item.son) {
      // console.log(item.son)
        return createElement('el-submenu', {
          attrs: {index: item.url}
        }, [
          createElement('template', {
            slot: 'title'
          }, [
            createElement('i', {
              attrs: {'class': 'iconfont'}
            }, [item.icon]),
            createElement('span', {
              attrs: {slot: 'title'}
            }, [item.name])
          ])
        ])
      } else {
        return createElement('el-menu-item', {
          attrs: {index: item.url}
        }, [
          createElement('i', {
            attrs: {'class': 'iconfont'}
          }, [item.icon]),
          createElement('span', {
            attrs: {slot: 'title'}
          }, [item.name])
        ])
      }
    })
  }
}

写完这个控制台抛出了个错误,提示我
图片说明
归根究底,技术有限,实在是搞的头大,希望大佬根据我写的组件模版,帮我用render函数写一个模版出来。供我学习,参考,使用。感激不尽!!!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

4条回答 默认 最新

  • dabocaiqq dabocaiqq 2019-08-05 10:46
    点赞 评论 复制链接分享
  • zatzat chen风 2019-08-09 01:43
    <template>
    <div>
      <el-menu
        background-color="#303133"
        text-color="#C0C4CC"
        active-text-color="#409EFF"
        class="el-menu"
        :collapse="true"
      >
      <navs :asideNav="asideNav"></navs>
      </el-menu>
        </div>
    </template>
    

    父组建错了, 只能一个root node,

    分给我吧,我要下载个文件

    点赞 评论 复制链接分享
  • qq_24394075 小斌爱敲代码玩 2019-08-12 21:54

    没人回答,我顶一下,没人回答我就在顶一下

    点赞 评论 复制链接分享
  • baidu_33552969 下一个喵呜 2019-08-29 19:40

    render 出来的只能有以恶搞根节点,所以你也是需要用div去包裹一下你需要render的哪一个item

    点赞 评论 复制链接分享

相关推荐