总结下Vue/React里的插槽

今天花几分钟给大家讲解一下"插槽"这个概念。目前前端主流的运行时框架里,插槽是绕不开的一个概念。究其原因是因为组件的渲染默认是结构式渲染。那啥又是结构式渲染?

上图就是一个很好的例子,渲染前是什么结构,渲染后就是什么结构。

那这个时候就会出现2类问题,如下:

  • 性价比。
  • 灵活度。

首先是性价比,有的时候,我们当前组件渲染在其他地方的性价比要比直接渲染在父节点里要高,比如Modal、Message这种全局提示类的组件。你说这种全局提示类的组件,能不能将dom放到父级节点里去实现?答案肯定是可以的,只不过这种做法会让你的Modal提示类组件在实现上受父级dom的限制,比如:

  • 如果你的Modal是绝对定位做的,那么你就一定要考虑父级以上dom它们的定位了。因为我们知道绝对定位相对的是第一个有定位的父元素。
  • 如果你的Modal是固定定位做的,那么父级dom隐藏的时候,你的子元素Modal组件是不是也没了呀。

其次我们再来说说灵活度的问题。有时候,我们想不到开发者具体想渲染什么元素,为了能够让开发者自己决定去渲染什么,我们需要这种机制,我们来提供多个渲染位置,用户想在什么位置渲染就在那个位置渲染。

所以插槽的概念出来了,它就是一种能够让用户在父节点外去渲染特定元素的一种机制

当前主流框架里,插槽是如何被使用的呢?

一、React

React.createPortal是官方提供的插槽机制,个人感觉,比Vue里的slot要方便很多。用法如下:

javascript 复制代码
React.createPortal(
    要插入的元素或者组件,
    要插入的位置
)

具体如何使用这个API去实现一个Modal提示类组件,更详细的请参考这篇文章

二、Vue

Vue也是一个出色的框架,但是我认为心智负担比React要重。在Vue里,插槽的使用分为两点,分别是插槽的位置插槽能够提供的数据

2.1、插槽的位置

一个组件可以暴露出多个插槽,那么此时用户该如何去指定某个具体的渲染位置呢?在官方文档里这叫做具名插槽

还是以下图为例:

<Child1>、<Child2>组件都是<Parent>组件的插槽元素,如果想要指定插槽元素在父元素里的渲染位置,父元素应该给<slot>标签指定name属性,用于给渲染位置进行名字标记,如下:

javascript 复制代码
// Parent组件如下:
<div class="parent">
    <slot name="position1"></slot>
    <slot name="position2"></slot>
</div>

同时子元素应该使用v-slot来指定渲染位置(注意,v-slot指令只能跟template标签配套使用哦),如下:

javascript 复制代码
<Parent>
    <template v-slot:position2>
        <Child1/>
    </template>
    <template v-slot:position1>
        <Child2/>
    </template>
</Parent>

这样,Child2组件的渲染位置就比Child1组件靠前。

2.2、插槽能够提供的数据

在官网里这叫插槽作用域。a.vue文件的代码如下:

javascript 复制代码
<Parent>
    <template v-slot:position2>
        <Child1/>
    </template>
    <template v-slot:position1>
        <Child2/>
    </template>
</Parent>

在a.vue单文件里,默认Child1、Child2组件能够绑定的属性都是a.vue文件里的data或者props。那如果我想绑定Parent组件里的属性呢?

这种情况也是很常见的,比如Table组件里的自定义列。你需要把当前行数据返回,这样用户才能自行决定如何渲染。

想要解决这个问题,操作如下:

1、在Parent组件里,给slot标签添加属性(动态或者静态的属性都可以,这两种属性的区别就是属性前面是否跟着v-bind指令)。

javascript 复制代码
// Parent组件如下:
<div class="parent">
    <slot :row1 = "data1" name="position1"></slot>
    <slot :row2 = "data2" name="position2"></slot>
</div>

<script>
export default {
  data(){
    return {
      data1: {},
      data2: {}
    }
  }
}
</script>

2、在a.vue文件里,给v-slot指令绑定value。

javascript 复制代码
<Parent>
    <template v-slot:position2="slot1">
        <Child1 :fatherData="slot1.data2"/>
    </template>
    <template v-slot:position1="slot2">
        <Child2 :fatherData="slot2.data1"/>
    </template>
</Parent>

这样,Child自组件就可以访问到父组件里的属性了。

三、最后

好啦,以上就是本篇文章的全部内容啦,如果你喜欢,欢迎3连支持;如果上述有表述不对的地方,欢迎指正,我们下期再见啦~~

相关推荐
kyriewen1 小时前
今年裁了16万技术人——但字节前端岗反而涨了23%
前端·javascript·面试
用户059540174461 小时前
把 AI Agent 记忆存储验证从 40 分钟手测压到 3 分钟,pytest + Docker 这套组合太顶了
前端·css
stereohomology1 小时前
MS Edge很多事的一点是把地址栏复制的地址自动转标题文本
前端·edge
imaol12 小时前
链表 -- 环链表
java·前端·链表
imaol12 小时前
链表 -- 双向链表
java·前端·链表
东风破_2 小时前
大前端手里的 Next.js:从 #root 到 SEO,一份 HTML 的两种命运
前端·后端
IT_陈寒2 小时前
Vue的v-for不听话?我被这个Key的坑整懵了
前端·人工智能·后端
众人皆醒我独醉3 小时前
训练加速实战:Flash Attention、Gradient Checkpointing 与数据流水线
后端·面试·gpu
Loveyourself3 小时前
Claude Code Memory 总体系核心代码逐行解析
面试·agent
王林不想说话3 小时前
ES6 到 ES2026 全面进阶指南:新特性、原理、示例与工程落地
前端·javascript·面试