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 相关文章推荐
vuex Module将 store 分割成模块的操作
Dec 07 Vue.js
Vue解决移动端弹窗滚动穿透问题
Dec 15 Vue.js
vue实现一个获取按键展示快捷键效果的Input组件
Jan 13 Vue.js
vue组件是如何解析及渲染的?
Jan 13 Vue.js
浅谈Vue开发人员的7个最好的VSCode扩展
Jan 20 Vue.js
深入了解Vue动态组件和异步组件
Jan 26 Vue.js
基于vue的video播放器的实现示例
Feb 19 Vue.js
vue-element-admin项目导入和导出的实现
May 21 Vue.js
SSM VUE Axios详解
Oct 05 Vue.js
vue配置型表格基于el-table拓展之table-plus组件
Apr 12 Vue.js
vue3.0 数字翻牌组件的使用方法详解
Apr 20 Vue.js
Vue2项目中对百度地图的封装使用详解
Jun 16 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
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
php之readdir函数用法实例
2014/11/13 PHP
php输出金字塔的2种实现方法
2014/12/16 PHP
制作特殊字的脚本
2006/06/26 Javascript
javascript同步Import,同步调用外部js的方法
2008/07/08 Javascript
href下载文件根据id取url并下载
2014/05/28 Javascript
在JS方法中返回多个值的方法汇总
2015/05/20 Javascript
浅谈JavaScript中指针和地址
2015/07/26 Javascript
iframe中子父类窗口调用JS的方法及注意事项
2015/08/25 Javascript
Jquery+ajax+JAVA(servlet)实现下拉菜单异步取值
2016/03/23 Javascript
详解NodeJS框架express的路径映射(路由)功能及控制
2017/03/24 NodeJs
JS排序之选择排序详解
2017/04/08 Javascript
ReactNative短信验证码倒计时控件的实现代码
2017/07/20 Javascript
js制作简单的音乐播放器的示例代码
2017/08/28 Javascript
js中document.write和document.writeln的区别
2018/03/11 Javascript
vue如何实现自定义底部菜单栏
2019/07/01 Javascript
js实现鼠标拖拽div左右滑动
2020/01/15 Javascript
详解JavaScript之Array.reduce源码解读
2020/11/01 Javascript
[42:20]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
Python提取网页中超链接的方法
2016/09/18 Python
Python DataFrame 设置输出不显示index(索引)值的方法
2018/06/07 Python
Python解析Excle文件中的数据方法
2018/10/23 Python
selenium+python自动化测试之多窗口切换
2019/01/23 Python
深入解析python中的实例方法、类方法和静态方法
2019/03/11 Python
python爬虫开发之Request模块从安装到详细使用方法与实例全解
2020/03/09 Python
在django admin中配置搜索域是一个外键时的处理方法
2020/05/20 Python
Python绘制数码晶体管日期
2021/02/19 Python
使用CSS3来绘制一个月食图案
2015/07/18 HTML / CSS
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
出国考察邀请函
2014/01/21 职场文书
党风廉政承诺书
2014/03/27 职场文书
出租车拒载检讨书
2015/01/28 职场文书
统计员岗位职责范本
2015/04/14 职场文书
2016全国“质量月”活动标语口号
2015/12/26 职场文书
源码安装apache脚本部署过程详解
2022/09/23 Servers