导读:本期聚焦于小伙伴创作的《JavaScript中如何使用插槽?Vue、React与Web Components实现详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中如何使用插槽?Vue、React与Web Components实现详解》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript中如何使用插槽

在JavaScript的组件化开发中,插槽(Slot)是实现内容分发的核心机制,它允许我们在组件内部预留占位区域,在使用组件时动态传入自定义内容。这一特性在Vue、React等框架中都有体现,不同框架的实现方式略有差异,下面我们分别介绍主流框架中的插槽用法。

Vue中的插槽使用

Vue对插槽的支持非常完善,分为默认插槽、具名插槽和作用域插槽三类,下面逐一说明。

默认插槽

默认插槽是最基础的插槽形式,组件内部用<slot>标签预留位置,使用时传入的内容会替换该<slot>标签。

首先定义带默认插槽的子组件:

<!-- 子组件 ChildComponent.vue -->
<template>
  <div class="child-container">
    <h3>子组件标题</h3>
    <!-- 默认插槽,未传入内容时显示默认文本 -->
    <slot>这是插槽的默认内容</slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
}
</script>

<style scoped>
.child-container {
  border: 1px solid #ccc;
  padding: 16px;
  margin: 8px 0;
}
</style>

然后在父组件中使用该子组件,传入自定义内容:

<!-- 父组件 ParentComponent.vue -->
<template>
  <div class="parent-container">
    <h2>父组件</h2>
    <!-- 不传入内容,使用子组件插槽默认内容 -->
    <ChildComponent />

    <!-- 传入自定义内容,替换子组件默认插槽 -->
    <ChildComponent>
      <p>这是父组件传入的自定义内容</p>
      <button>点击按钮</button>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  name: 'ParentComponent',
  components: {
    ChildComponent
  }
}
</script>

具名插槽

当组件需要多个插槽时,可以通过给<slot>添加name属性定义具名插槽,使用时通过v-slot指令指定要替换的插槽名称。

先修改子组件,添加多个具名插槽:

<!-- 子组件 ChildComponent.vue -->
<template>
  <div class="child-container">
    <header>
      <!-- 名为header的具名插槽 -->
      <slot name="header">默认头部内容</slot>
    </header>
    <main>
      <!-- 默认插槽,等价于 name="default" -->
      <slot>默认主体内容</slot>
    </main>
    <footer>
      <!-- 名为footer的具名插槽 -->
      <slot name="footer">默认底部内容</slot>
    </footer>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
}
</script>

父组件中使用具名插槽:

<!-- 父组件 ParentComponent.vue -->
<template>
  <div class="parent-container">
    <ChildComponent>
      <!-- v-slot:header 可简写为 #header -->
      <template #header>
        <h3>自定义头部标题</h3>
      </template>

      <!-- 默认插槽内容 -->
      <p>这是自定义的主体内容,会替换默认插槽</p>

      <template #footer>
        <p>自定义底部信息 © 2024</p>
      </template>
    </ChildComponent>
  </div>
</template>

作用域插槽

作用域插槽允许子组件向父组件传递数据,父组件在使用插槽时可以根据子组件传递的数据渲染内容。

子组件中通过给<slot>绑定属性传递数据:

<!-- 子组件 ChildComponent.vue -->
<template>
  <div class="child-container">
    <h3>用户列表</h3>
    <ul>
      <li v-for="user in userList" :key="user.id">
        <!-- 向父组件传递user数据 -->
        <slot name="user" :userInfo="user">
          {{ user.name }} - {{ user.age }}岁
        </slot>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  data() {
    return {
      userList: [
        { id: 1, name: '张三', age: 25 },
        { id: 2, name: '李四', age: 28 },
        { id: 3, name: '王五', age: 22 }
      ]
    }
  }
}
</script>

父组件中接收作用域插槽传递的数据:

<!-- 父组件 ParentComponent.vue -->
<template>
  <div class="parent-container">
    <ChildComponent>
      <!-- 接收子组件传递的userInfo数据,解构赋值获取 -->
      <template #user="{ userInfo }">
        <span style="color: #1890ff">
          {{ userInfo.name }}(年龄:{{ userInfo.age }})
        </span>
      </template>
    </ChildComponent>
  </div>
</template>

React中的插槽实现

React本身没有内置的插槽语法,通常通过props.children来实现类似插槽的内容分发功能,也可以自定义props来模拟具名插槽。

通过children实现默认插槽

子组件通过props.children获取父组件传入的子元素,实现默认插槽的效果:

// 子组件 ChildComponent.jsx
import React from 'react';

const ChildComponent = (props) => {
  return (
    <div style={{ border: '1px solid #ccc', padding: '16px', margin: '8px 0' }}>
      <h3>子组件标题</h3>
      {/* 渲染父组件传入的内容,等价于默认插槽 */}
      {props.children || <p>这是插槽的默认内容</p>}
    </div>
  );
};

export default ChildComponent;

父组件使用:

// 父组件 ParentComponent.jsx
import React from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  return (
    <div>
      <h2>父组件</h2>
      {/* 不传入children,使用默认内容 */}
      <ChildComponent />

      {/* 传入自定义children,替换默认内容 */}
      <ChildComponent>
        <p>这是父组件传入的自定义内容</p>
        <button onClick={() => alert('点击了按钮')}>点击按钮</button>
      </ChildComponent>
    </div>
  );
};

export default ParentComponent;

自定义props模拟具名插槽

React中可以通过给子组件传递不同名称的props,模拟具名插槽的效果:

// 子组件 ChildComponent.jsx
import React from 'react';

const ChildComponent = (props) => {
  return (
    <div style={{ border: '1px solid #ccc', padding: '16px' }}>
      <header>
        {/* 渲染header插槽内容,无内容则显示默认 */}
        {props.header || <p>默认头部内容</p>}
      </header>
      <main>
        {/* 渲染主体内容 */}
        {props.children || <p>默认主体内容</p>}
      </main>
      <footer>
        {/* 渲染footer插槽内容 */}
        {props.footer || <p>默认底部内容</p>}
      </footer>
    </div>
  );
};

export default ChildComponent;

父组件中使用:

// 父组件 ParentComponent.jsx
import React from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  return (
    <div>
      <ChildComponent
        header={<h3>自定义头部标题</h3>}
        footer={<p>自定义底部信息 © 2024</p>}
      >
        <p>这是自定义的主体内容</p>
      </ChildComponent>
    </div>
  );
};

export default ParentComponent;

原生Web Components中的插槽

Web Components规范原生支持插槽,通过<slot>标签实现,和Vue的默认插槽、具名插槽逻辑类似。

首先定义自定义元素:

// 定义自定义元素
class MyCard extends HTMLElement {
  constructor() {
    super();
    // 创建影子DOM,隔离样式
    const shadow = this.attachShadow({ mode: 'open' });

    // 创建卡片容器
    const container = document.createElement('div');
    container.style.border = '1px solid #ccc';
    container.style.padding = '16px';
    container.style.margin = '8px 0';

    // 添加标题区域
    const title = document.createElement('h3');
    title.textContent = '卡片标题';
    container.appendChild(title);

    // 添加默认插槽
    const defaultSlot = document.createElement('slot');
    defaultSlot.textContent = '这是插槽的默认内容';
    container.appendChild(defaultSlot);

    // 添加具名插槽
    const footer = document.createElement('div');
    footer.style.marginTop = '12px';
    const footerSlot = document.createElement('slot');
    footerSlot.name = 'footer';
    footerSlot.textContent = '默认底部内容';
    footer.appendChild(footerSlot);
    container.appendChild(footer);

    shadow.appendChild(container);
  }
}

// 注册自定义元素
customElements.define('my-card', MyCard);

在HTML中使用该自定义元素:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Web Components插槽示例</title>
</head>
<body>
  <my-card>
    <p>这是传入的默认插槽内容</p>
    <!-- 具名插槽内容,通过slot属性指定 -->
    <p slot="footer">自定义底部信息</p>
  </my-card>

  <script src="my-card.js"></script>
</body>
</html>

插槽使用注意事项

  • Vue中的作用域插槽数据传递是单向的,父组件只能读取子组件传递的数据,无法直接修改。
  • React的children可以是任意合法的React节点,包括字符串、数字、元素、数组等,使用时需要做非空判断避免报错。
  • Web Components的<slot>标签只在影子DOM中生效,普通DOM中不会解析该标签。
  • 插槽内容的作用域属于父组件,子组件无法直接访问插槽内的变量,作用域插槽就是为了解决这个问题。

JavaScript插槽Vue插槽React childrenWeb Components组件内容分发 本作品最后修改时间:2026-05-23 23:16:03

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。