插槽vue/react

​作用域插槽(Scoped Slots)​ ​ 是 Vue 提供的一种​​让插槽内容可以访问子组件内部数据​ ​的机制,它极大地增强了组件的​​灵活性与复用性​​,是 Vue 组件设计中非常强大的功能之一。


一、vue插槽

先回顾:普通插槽(默认插槽、具名插槽)

在 Vue 中,插槽(slot)是​​父组件向子组件传递一段模板内容(HTML / 组件)的机制​ ​,用于实现​​内容分发​​。比如:

复制代码
<!-- 子组件 Child.vue -->
<template>
  <div>
    <slot></slot>  <!-- 普通插槽 -->
  </div>
</template>

<!-- 父组件 -->
<Child>
  <p>这是插入到子组件中的内容</p>  <!-- 父组件传的内容 -->
</Child>

✅ 这是​​普通插槽​ ​,父组件传什么,子组件就在 <slot>的位置显示什么。


那什么是​​作用域插槽​​呢?

​作用域插槽(Scoped Slot)​ ​ 是一种特殊的插槽,它允许​​父组件在插入内容时,可以访问子组件内部的数据​​。

作用域插槽的核心作用,就是让子组件可以把内部的数据"暴露"给父组件,让父组件可以基于这些数据,自由地决定如何渲染插槽内容。​

换句话说:

  • 通常插槽是​​父 → 子 传内容​​;

  • 但作用域插槽是​​子 → 父 传数据,让父组件决定如何渲染这些数据​​。


🔧 作用域插槽的语法(Vue 2 & Vue 3)


✅ Vue 2 中的作用域插槽语法

在子组件中,给 <slot>绑定数据:

javascript 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div>
    <slot :user="user" :items="items"></slot>
    <!-- 把 user 和 items 数据暴露给父组件插槽内容 -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: { name: 'Alice', age: 25 },
      items: ['Apple', 'Banana', 'Cherry']
    };
  }
};
</script>

在父组件中,通过 ​​v-slot(或 slot-scope)​​ 接收子组件传递的数据:

javascript 复制代码
<!-- 父组件 -->
<template>
  <Child>
    <!-- Vue 2 写法1:slot-scope(旧版) -->
    <template slot-scope="{ user, items }">
      <p>用户名:{{ user.name }}</p>
      <ul>
        <li v-for="item in items" :key="item">{{ item }}</li>
      </ul>
    </template>
  </Child>
</template>

或者 Vue 2 也支持新版语法(推荐,和 Vue 3 类似):

javascript 复制代码
<Child>
  <template #default="{ user, items }">
    <p>{{ user.name }}</p>
    <ul>
      <li v-for="item in items" :key="item">{{ item }}</li>
    </ul>
  </template>
</Child>

✅ Vue 3 中的作用域插槽语法(更统一、更简洁)

在子组件中,同样通过 <slot :data="xxx">传递数据:

javascript 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div>
    <slot :user="user" :items="items"></slot>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const user = ref({ name: 'Alice', age: 25 });
const items = ref(['Apple', 'Banana', 'Cherry']);
</script>

在父组件中,使用 ​​v-slot​ ​ 或 ​​#​​ 语法接收:

javascript 复制代码
<template>
  <Child>
    <template #default="{ user, items }">
      <p>用户:{{ user.name }}, 年龄:{{ user.age }}</p>
      <ul>
        <li v-for="item in items" :key="item">{{ item }}</li>
      </ul>
    </template>
  </Child>
</template>

✅ 推荐使用 ​#default="{ ... }"​ 这种简洁写法(Vue 3)



📌 作用域插槽的典型应用场景(附例子)


✅ 场景 1:​​列表组件(父组件自定义每一项的展示)​

子组件:ItemList.vue
复制代码
<template>
  <ul>
    <li v-for="(item, index) in items" :key="index">
      <!-- 把 item 数据通过作用域插槽暴露出去 -->
      <slot :item="item" :index="index"></slot>
    </li>
  </ul>
</template>

<script setup>
defineProps(['items'])
</script>
父组件:
复制代码
<template>
  <ItemList :items="data">
    <template #default="{ item, index }">
      <span>第 {{ index }} 项:{{ item.name }}</span>
    </template>
  </ItemList>
</template>

<script setup>
import ItemList from './ItemList.vue'

const data = [
  { name: 'Apple' },
  { name: 'Banana' },
  { name: 'Cherry' }
]
</script>

🔍 ​​效果:​​ 子组件负责循环渲染列表,但每一项显示什么内容,由父组件通过插槽自定义!


✅ 场景 2:​​卡片组件(父组件自定义卡片内容)​

子组件:Card.vue
复制代码
<template>
  <div class="card">
    <slot :title="title" :content="content"></slot>
  </div>
</template>

<script setup>
defineProps(['title', 'content'])
</script>
父组件:
复制代码
<template>
  <Card :title="'Hello'" :content="'Vue is awesome'">
    <template #default="{ title, content }">
      <h3>{{ title }}</h3>
      <p>{{ content }}</p>
    </template>
  </Card>
</template>

你问的是:​​"React 怎么实现类似 Vue 的插槽(slot)的功能?"​

这是一个非常重要且实用的跨框架对比问题!🎯

在 Vue 中,​​插槽(slot)​ ​ 是一种非常核心的组件内容分发机制,它让​​父组件可以向子组件传递一段模板内容(UI 片段)​ ​,从而实现​​高复用、灵活定制的组件设计​​。

而 React ​​本身没有直接叫"插槽"的概念​ ​,但完全可以通过 ​​React 的组件设计模式 + props(特别是 children 和 render props)​ ​ 轻松实现 ​​类似 Vue 插槽的功能​​,甚至更灵活!


二、🔧 2. React 中如何实现类似 Vue "插槽" 的功能?

​React 没有 Vue 那样的 <slot>标签,但可以通过 props.children实现默认插槽,通过命名 props(如 header、main)实现具名插槽,通过函数 props(如 renderXXX)实现作用域插槽,从而达到与 Vue 插槽几乎相同的组件内容分发与定制能力,而且同样灵活强大!​


✅ 方法一:使用 childrenprops(实现默认插槽)

​React 中,父组件传递给子组件的 JSX 内容,可以通过 props.children获取!​

这相当于 Vue 的 ​​默认插槽​​。


📌 示例:React 实现默认插槽(类似 Vue 的 <slot>
子组件:Child.js
javascript 复制代码
function Child(props) {
  return (
    <div>
      <h2>这是子组件</h2>
      {/* React 中通过 props.children 获取父组件传入的内容 */}
      {props.children}
    </div>
  );
}

export default Child;
父组件:App.js
javascript 复制代码
import Child from './Child';

function App() {
  return (
    <Child>
      <p>🎉 这段内容就是插槽内容,会显示在子组件里的 {props.children} 位置</p>
    </Child>
  );
}

🔍 ​​效果:​

父组件在 <Child>标签内写的内容,会通过 props.children渲染到子组件中,就像 Vue 的 <slot>一样。

✅ ​​这就是 React 实现 Vue 默认插槽的方式!​


✅ 方法二:实现类似 Vue 的​​具名插槽

在 Vue 中,你可以有多个具名插槽,比如:

复制代码
<template>
  <div>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

父组件可以这样传:

复制代码
<Child>
  <template v-slot:header>这是头部</template>
  <p>这是默认内容</p>
  <template v-slot:footer>这是页脚</template>
</Child>

✅ React 中如何实现具名插槽?

React 没有 v-slot:name,但可以通过 ​​传递对象形式的 children 或命名 props​​ 来模拟!

推荐方式:通过 props 传入不同区块内容(模拟具名插槽)
子组件:Child.js
javascript 复制代码
function Child({ header, main, footer }) {
  return (
    <div>
      {header && <header>{header}</header>}
      <main>{main}</main>
      {footer && <footer>{footer}</footer>}
    </div>
  );
}

export default Child;
父组件:App.js
javascript 复制代码
import Child from './Child';

function App() {
  return (
    <Child
      header={<h1>这是头部(类似具名插槽 header)</h1>}
      main={<p>这是主要内容(类似默认插槽)</p>}
      footer={<footer>这是页脚(类似具名插槽 footer)</footer>}
    />
  );
}

🔍 ​​说明:​

  • 不像 Vue 那样用 <template v-slot:name>,而是​​通过 props 传入不同区块的 JSX​

  • 比如:header={<h1>...</h1>}main={<p>...</p>}footer={...}

  • 这是 React 社区中非常常见且清晰的实现具名插槽的方式 ✅


✅ 方法三:更灵活的方式 ------ ​​使用 Render Props(高级用法)​

​Render Props 是一种 React 设计模式,允许你通过一个函数 prop,把渲染逻辑交给父组件控制,从而实现更灵活的"插槽"或内容分发。​

不过,对于大多数"插槽"场景,children或 ​​命名 props​ ​ 已经足够,​​Render Props 更适合控制渲染逻辑,而非单纯的内容分发。​

但为了完整性,简单介绍一下:

子组件:
复制代码
function SlotDemo({ renderHeader, renderContent }) {
  return (
    <div>
      {renderHeader && renderHeader()}
      <main>{renderContent && renderContent()}</main>
    </div>
  );
}
父组件:
复制代码
<SlotDemo
  renderHeader={() => <h1>这是通过函数传入的头部</h1>}
  renderContent={() => <p>这是通过函数传入的内容</p>}
/>

🔒 ​​适用场景更复杂,比如子组件控制何时渲染、如何传参等,但代码可读性稍差,一般推荐上面 children / props 方式。​


三、🔍 3. 对比 Vue 插槽 和 React 实现方式

功能 Vue 插槽 React 实现方式
​默认插槽​ <slot></slot> 通过 props.children获取 <Child>...</Child>中的内容
​具名插槽​ <slot name="xxx">+ <template v-slot:xxx> 通过 props 传入不同 JSX 块:header={<h1>...}, main={...}
​作用域插槽​ <slot :data="xxx">,父组件接收数据 通过 props 传数据给父组件传入的函数或组件,比如 <slot data={data} />→ 父组件用 {data}
​灵活度​ 高,语法清晰 同样高,但语法习惯不同(更灵活、更 JS 风格)
相关推荐
许___3 小时前
Vue使用原生方式把视频当作背景
前端·javascript·vue.js
萌萌哒草头将军3 小时前
尤雨溪强烈推荐的这个库你一定要知道 ⚡️⚡️⚡️
前端·vue.js·vite
2401_878454533 小时前
Vue 核心特性详解:计算属性、监听属性与事件交互实战指南
前端·vue.js·交互
GISer_Jing4 小时前
Next.js数据获取演进史
java·开发语言·javascript
wangpq5 小时前
使用rerender-spa-plugin在构建时预渲染静态HTML文件优化SEO
前端·javascript·vue.js
前端开发爱好者5 小时前
弃用 uni-app!Vue3 的原生 App 开发框架来了!
前端·javascript·vue.js
PairsNightRain5 小时前
React.lazy 和 suspense 如何使用?
前端·javascript·react.js
渣哥5 小时前
三级缓存揭秘:Spring 如何优雅地处理循环依赖问题
javascript·后端·面试
车前端5 小时前
理解 React 状态管理
react.js