IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue 递归组件 递归组件中的插槽 -> 正文阅读

[JavaScript知识库]vue 递归组件 递归组件中的插槽

需求:

????????在开发中需要一个公共组件Tree(树),接受的数据是典型的树结构数据,当前项数据是? ? ? ?一个对象,如果有子节点,拥有一个children属性。我并不希望每一项的数据展现形式是定死的,而是通过插槽能够自定义。

假设:

<template>
  <ul class="tree-wrapper">
    <li v-for="(item, index) in list" :key="index" @click.stop="change(item)">
      <div class="content" :class="{ active: item.active }">
        <slot :row="item">{{ item.name }}</slot>
      </div>
      <Tree :list="item.children" @change="change">
        <slot :row="item">{{ item.name }}</slot>
      </Tree>
    </li>
  </ul>
</template>

<script>
export default {
  name: 'Tree',
  props: {
    list: {
      type: Array,
      default: () => [],
    },
  },
  methods: {
    change(item) {
      if (!item.active) {
        this.$emit('change', item);
      }
    },
  },
};
</script>
<template>
  <div class="blog-type-wrapper" v-loading="isLoading">
    <Tree :list="typeList" @change="handleChange('categoryID', $event)">
      <template #default="{ row }">
        <span class="name">{{ row.name }}</span>
        <span class="num">{{ row.articleCount }}篇</span>
      </template>
    </Tree>
  </div>
</template>

问题:

? ? ? ? 在组件内部可以通过定义name标识组件,然后使用name名称作为组件名称,实现递归调用,但是递归引用处的插槽内容如何通过外部定义呢?递归内部的数据又如何传递呢?

?解决:

? ? ? ? 使用模板的形式不是很好处理此问题,使用render函数替代模板可以很好的解决


<script>
export default {
  render(h) {
    //c2函数用于处理动态的插槽部分
    const c2 = (item) => {
      const arr = [
        h(
          'div',
          {
            class: {
              content: true, //静态类名
              active: item.active, //动态类名
            },
          },
          this.$scopedSlots.default
            ? this.$scopedSlots.default({ row: item }) //相当于作用域插槽
            : item.name //相当于插槽默认值
        ),
      ];
      //如果存在子级,使用递归处理
      if (item.children && item.children.length > 0) {
        arr.push(c1(item.children));
      }
      return arr;
    };

    //c1函数用于处理固定结构部分(例如ul为父级,每个数据项对应一个li子级)
    const c1 = (list) => {
      const lis = list.map((item, index) => {
        return h(
          'li',
          {
            attrs: {
              key: index, //key标识
            },
            on: {
              click: (event) => {
                event.stopPropagation(); //阻止事件冒泡,为了精确处理每一项子级的事件
                if (!item.active) {
                  this.$emit('change', item);
                }
              },
            },
          },
          c2(item)
        );
      });

      const ul = h(
        'ul',
        {
          class: {
            'tree-wrapper': true,
          },
        },
        lis
      );
      return ul;
    };

    return c1(this.$attrs.list);
  },
};
</script>

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-08 11:42:45  更:2021-10-08 11:43:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:01:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码