插槽vue/react - 详解

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


一、vue插槽

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

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





  

这是插入到子组件中的内容

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


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

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

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

换句话说:

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

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


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


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

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



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

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


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


  

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

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



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

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

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



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


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

子组件:ItemList.vue

<script setup>
defineProps(['items'])
</script>
父组件:

<script setup>
import ItemList from './ItemList.vue'
const data = [
  { name: 'Apple' },
  { name: 'Banana' },
  { name: 'Cherry' }
]
</script>

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


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

子组件:Card.vue

<script setup>
defineProps(['title', 'content'])
</script>
父组件:

你问的是:​​“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
function Child(props) {
  return (
    

这是子组件

{/* React 中通过 props.children 获取父组件传入的内容 */} {props.children}
); } export default Child;
父组件:App.js
import Child from './Child';
function App() {
  return (
    
      

这段内容就是插槽内容,会显示在子组件里的 {props.children} 位置

); }

​效果:​

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

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


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

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

父组件可以这样传:


  
  

这是默认内容


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

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

推荐方式:​​通过 props 传入不同区块内容(模拟具名插槽)​
子组件:Child.js
function Child({ header, main, footer }) {
  return (
    
{header &&
{header}
}
{main}
{footer &&
{footer}
}
); } export default Child;
父组件:App.js
import Child from './Child';
function App() {
  return (
    这是头部(类似具名插槽 header)}
      main={

这是主要内容(类似默认插槽)

} 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 (
    
{renderHeader && renderHeader()}
{renderContent && renderContent()}
); }
父组件:
 

这是通过函数传入的头部

} renderContent={() =>

这是通过函数传入的内容

} />

​适用场景更复杂,比如子组件控制何时渲染、如何传参等,但代码可读性稍差,一般推荐上面 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 风格)

posted on 2025-11-08 18:51  slgkaifa  阅读(1)  评论(0)    收藏  举报

导航