插槽意义和实现
- 意义: 让组件具备更强的通用性,组件内容不限制是某种元素,而是由使用组件的人来决定渲染的内容
- 实现:
Vue
通过 <slot>
标签完成,而 React
有以下两种方案实现
children插槽
- 每个组件都可以获取到
props.children
,其包含组件的开始标签和结束标签之间的内容
- 首先在父组件的子组件标签中插入内容
class App extends Component {
render() {
return (
<div className='app'>
{/* 父组件中插入内容 */}
<NavBar>
<button>左边按钮</button>
<h2>中间标题</h2>
<i>右边文字</i>
</NavBar>
</div>
)
}
}
- 然后在子组件内部通过
this.props.children
获取,它是个包含所有插入元素的数组
class NavBar extends Component {
render() {
const { children } = this.props
return (
<div className='nav-bar'>
<div className="left">{children[0]}</div>
<div className="center">{children[1]}</div>
<div className="right">{children[2]}</div>
</div>
)
}
}

- 注意: 当子组件标签中只有一个元素时,
this.props.children
就是其本身,并非数组
- 如果需要限制使用者是传一个元素还是传多个元素,可以通过
propTypes
做类型限制
static propTypes = {
children: propTypes.array
}
static propTypes = {
children: propTypes.element
}
props插槽
props
除了可以用于组件通信外,还允许直接传递 React
元素,用于实现插槽
- 在父组件的子组件标签上将插入内容,按照
属性名={React元素}
进行传递
class App extends Component {
render() {
return (
<div className='app'>
{/* 父组件中插入内容 */}
<NavBar
leftSlot={<button>左边按钮</button>}
centerSlot={<h2>中间标题</h2>}
rightSlot={<i>右边文字</i>}
/>
</div>
)
}
}
- 在子组件内部的
this.props
获取传递的内容
class NavBar extends Component {
render() {
const { leftSlot, centerSlot, rightSlot } = this.props
return (
<div className='nav-bar'>
<div className="left">{leftSlot}</div>
<div className="center">{centerSlot}</div>
<div className="right">{rightSlot}</div>
</div>
)
}
}
作用域插槽(render props)
- 在
Vue
中的子组件实现插槽之后,可以向外暴露内部的数据,当父组件使用该插槽时就可以拿到对应的数据,这就是 Vue
的作用域插槽
Vue
的作用域插槽本质是将插槽内容包裹在一个拥有单个参数的函数里,而 React
也可以运用这个原理,实现作用域插槽
- 首先在子组件标签中通过
props
传入一个返回 React
元素的函数
class App extends Component {
render() {
return (
<div className='app'>
<NavBar scopedSlot={(data)=><h1>{data}</h1>}/>
</div>
)
}
}
- 在子组件中调用
scopedSlot
函数,并传入参数
class NavBar extends Component {
render() {
const { scopedSlot } = this.props
return (
<div className='nav-container'>
{scopedSlot('scopedSlot render')}
</div>
)
}
}
