Vue如何跨组件传递Slot的实现


Posted in Vue.js onDecember 14, 2020

在开发过程中遇到这样一个问题,如何跨组件传递插槽。因为在开发类似树组件的过程中,插槽需要通过外部传递到树的根节点,然后通过根节点依次传递到各个叶子节点。那么如何把根节点的Slot如传递给子组件呢?
我们在开发过程中,希望可以这样实现重新定义叶子节点的结构:

<data-tree>
 <template v-slot:node="data">
   <div>{{data.title}} - {{data.text}}</div>
  </template>
</data-tree>

那么如何在组件内传递Slot就是一个问题。

嵌套传递

通过固定级别的组件结构里可以通过直接书写<v-slot ...>来传递对应的Slot元素,来实现一层一层的传递。

<data-tree>
 <data-tree-item>
   <template :node="data">
      <slot :data="data"> xxx </slot>
    </template>
  </data-tree-item>
</data-tree>

通过在外层创建slot可以逐层将slot进行传递,但是如果过多的嵌套层次,这样就显得很麻烦。

Render

还有一种方案是通过Render函数来进行显示,可以通过$slots来访问当前组件的slot元素,然后通过Render函数创建新组件时,将slot传递给下一层。

h('data-tree-item',{
 scopedSlots: {
    node: props => this.$slots.node(props)
  },
})

这样通过Render子元素就可以接受到对应的Slot,也实现了传递。

动态组件

还有一种方式是通过动态组件,也是认为比较推荐的实现方式,不是通过传递Slot,而是通过子节点主动去获取根节点的Slot对象,然后直接在UI中渲染出来。

为此我们需要创建一个组件来渲染对应的Slot对象。

首先需要获取根节点:

const rootComponentName = 'data-tree'
/**
 * 获取父组件
 */
const getRootComponent = (
  component: ComponentInternalInstance | null
): ComponentInternalInstance | undefined => {
  if (component && component.type.name === rootComponentName) {
    return component
  }

  if (component && component.parent) {
    const parent = component.parent
    return getRootComponent(parent)
  }
}

通过递归我们可以获取到对应的父节点,这样我们就可以把Slot作为Data暴露出来

setup(props) {
    // 获取根节点
    const dataTree = getRootComponent(getCurrentInstance())
    const parentSlots = dataTree?.slots
    const nodeTemplate = parentSlots?.node as any
    return {
      nodeTemplate
    }
  }

这时候我们需要一个组件来渲染暴露出来的Slot:

components: {
    TemplateContainer: {
      functional: true,
      props: {
        template: {
          type: Function
        },
        data: {
          type: Object
        }
      },
      render: (props, ctx) => h('div', [props.template(props.data)])
    }
  }

好了现在该准备的都准备好了,可以去实现UI的显示了:

<template-container
          v-if="nodeTemplate"
          :template="nodeTemplate"
          :data="node">
</template-container>
<template v-else>
    {{ node.label }}
</template>

这样我们就实现了类似下面定义Slot的传递,也解决了我们跨组件传递Slot的问题。

<slot :data="node" name="node">
 {{ node.label }}
</slot>

本文使用的是Vue 3的事例,Vue 2也是相同的概念,在Vue 3中除了使用getRootComponent来查询跟节点,也可以使用Provide/Inject来将Slot主动传递给子节点。

到此这篇关于Vue如何跨组件传递Slot的实现的文章就介绍到这了,更多相关Vue 跨组件传递Slot内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例
Nov 20 Vue.js
Vue+penlayers实现多边形绘制及展示
Dec 24 Vue.js
vue3自定义dialog、modal组件的方法
Jan 04 Vue.js
vuex的使用步骤
Jan 06 Vue.js
基于vuex实现购物车功能
Jan 10 Vue.js
vue keep-alive的简单总结
Jan 25 Vue.js
Vue单页面应用中实现Markdown渲染
Feb 14 Vue.js
vue常用高阶函数及综合实例
Feb 25 Vue.js
vue3.0 项目搭建和使用流程
Mar 04 Vue.js
关于Vue中的options选项
Mar 22 Vue.js
Vue中使用import进行路由懒加载的原理分析
Apr 01 Vue.js
vue 自定义组件添加原生事件
Apr 21 Vue.js
VUE中鼠标滚轮使div左右滚动的方法详解
Dec 14 #Vue.js
vue3.0实现插件封装
Dec 14 #Vue.js
vue 基于abstract 路由模式 实现页面内嵌的示例代码
Dec 14 #Vue.js
Vue实现点击当前行变色
Dec 14 #Vue.js
Vue实现简单购物车功能
Dec 13 #Vue.js
vue使用element-ui实现表单验证
Dec 13 #Vue.js
vue+element实现动态加载表单
Dec 13 #Vue.js
You might like
德生1994机评
2021/03/02 无线电
2019年中国咖啡业现状与发展趋势
2021/03/04 咖啡文化
PHP数组内存耗用太多问题的解决方法
2010/04/05 PHP
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
Laravel 中使用 Vue.js 实现基于 Ajax 的表单提交错误验证操作
2017/06/30 PHP
PHP 面向对象程序设计之类属性与类常量实现方法分析
2020/04/13 PHP
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
ExtJS Window 最小化的一种方法
2009/11/18 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
基于jQuery实现返回顶部实例代码
2016/01/01 Javascript
详解a++和++a的区别
2017/08/30 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
Vue多系统切换实现方案
2018/06/05 Javascript
vue iview多张图片大图预览、缩放翻转
2019/07/13 Javascript
Python中使用pprint函数进行格式化输出的教程
2015/04/07 Python
Django接受前端数据的几种方法总结
2016/11/04 Python
浅谈Python中的bs4基础
2018/10/21 Python
详解pandas安装若干异常及解决方案总结
2019/01/10 Python
python自制包并用pip免提交到pypi仅安装到本机【推荐】
2019/06/03 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
深入了解Python在HDA中的应用
2019/09/05 Python
使用virtualenv创建Python环境及PyQT5环境配置的方法
2019/09/10 Python
在python shell中运行python文件的实现
2019/12/21 Python
浅谈python中频繁的print到底能浪费多长时间
2020/02/21 Python
Python字典dict常用方法函数实例
2020/11/09 Python
美体小铺法国官方网站:The Body Shop法国
2020/06/04 全球购物
建筑设计学生的自我评价
2014/01/16 职场文书
工商治理实习生的自我评价分享
2014/02/20 职场文书
三好生演讲稿
2014/09/12 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
小学优秀教师材料
2014/12/15 职场文书
酒会邀请函
2015/01/31 职场文书
2019年工作总结范文
2019/05/21 职场文书
《中国机长》观后感:敬畏生命,敬畏职责
2019/11/12 职场文书
浅谈Python列表嵌套字典转化的问题
2021/04/07 Python
django如何自定义manage.py管理命令
2021/04/27 Python