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 的异常处理机制
Nov 30 Vue.js
Vue router传递参数并解决刷新页面参数丢失问题
Dec 02 Vue.js
vuex Module将 store 分割成模块的操作
Dec 07 Vue.js
Vue 实现一个简单的鼠标拖拽滚动效果插件
Dec 10 Vue.js
如何在vue中使用kindeditor富文本编辑器
Dec 19 Vue.js
vue 动态生成拓扑图的示例
Jan 03 Vue.js
vue项目如何监听localStorage或sessionStorage的变化
Jan 04 Vue.js
Vuex实现简单购物车
Jan 10 Vue.js
使用vue3重构拼图游戏的实现示例
Jan 25 Vue.js
如何封装Vue Element的table表格组件
Feb 06 Vue.js
Vue-router编程式导航的两种实现代码
Mar 04 Vue.js
深入理解Vue的数据响应式
May 15 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
php中http_build_query 的一个问题
2012/03/25 PHP
php cli配置文件问题分析
2015/10/15 PHP
PHP面试题之文件目录操作
2015/10/15 PHP
PHP流Streams、包装器wrapper概念与用法实例详解
2017/11/17 PHP
javascript 网页跳转的方法
2008/12/24 Javascript
javascript FormatNumber函数实现方法
2008/12/30 Javascript
js 获取和设置css3 属性值的实现方法
2013/05/06 Javascript
谈谈对offsetleft兼容性的理解
2015/11/11 Javascript
一起学写js Calender日历控件
2016/04/14 Javascript
AngularJS  自定义指令详解及实例代码
2016/09/14 Javascript
JS封装的选项卡TAB切换效果示例
2016/09/20 Javascript
JS FormData上传文件的设置方法
2017/07/05 Javascript
Javascript 严格模式use strict详解
2017/09/16 Javascript
Node.js学习之查询字符串解析querystring详解
2017/09/28 Javascript
vue完成项目后,打包成静态文件的方法
2018/09/03 Javascript
基于小程序请求接口wx.request封装的类axios请求
2020/07/02 Javascript
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
Python判断文本中消息重复次数的方法
2016/04/27 Python
python之文件的读写和文件目录以及文件夹的操作实现代码
2016/08/28 Python
解决python 输出是省略号的问题
2018/04/19 Python
使用pandas将numpy中的数组数据保存到csv文件的方法
2018/06/14 Python
python url 参数修改方法
2018/12/26 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
Python 的AES加密与解密实现
2019/07/09 Python
CSS3实现各种图形的示例代码
2016/10/19 HTML / CSS
基于 HTML5 WebGL 实现的医疗物流系统
2019/10/08 HTML / CSS
优秀经理事迹材料
2014/02/01 职场文书
公务员转正考察材料
2014/02/07 职场文书
保证书范文大全
2014/04/28 职场文书
秋冬农业生产标语
2014/10/09 职场文书
工作失职自我检讨书
2015/05/05 职场文书
css3 利用transform-origin 实现圆点分布在大圆上布局及旋转特效
2021/04/29 HTML / CSS
Android基于Fresco实现圆角和圆形图片
2022/04/01 Java/Android
用Python仅20行代码编写一个简单的端口扫描器
2022/04/08 Python
vue项目配置sass及引入外部scss文件
2022/04/14 Vue.js
HTML中实现音乐或视频自动播放案例详解
2022/05/30 HTML / CSS