最近也学习了React
一段时间了,之前都是写Vue
,所以在这个过程中难免就会有一些比较。我也就是一激灵,Vue
的slot
其实蛮神奇的,那React
有slot
吗?
本篇文章你将会了解到:
Vue
的插槽使用
React
来使用插槽
React
来实现匿名插槽React
来实现具名插槽antd
的React
实现注意
:文章不包括项目搭建,只有核心代码
slot
呢?
Button
,是个按钮组件,然后你想给Button
一个名字<Button>我是button</Button>
我是button
被吃掉了slot
的官方解释
<slot>
元素作为组件模板之中的内容分发插槽。<slot>
元素自身将被替换。HelloWorld
组件如下,里面实际是一个button
<script setup>
</script>
<template>
<button>
<slot></slot>
</button>
</template>
<style scoped>
</style>
App.vue
中来调用<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<HelloWorld>
我是按钮
</HelloWorld>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
因为我们在组件的button
里面放了一个slot
,所以这个位置会空出来用来放输入的插槽内容,那么这个我是按钮
就会被接收
OK!那么现在,我们就对slot
有一个初步的认识了,那么,可以有多个插槽吗?
HelloWorld
组件如下:<script setup>
</script>
<template>
<div>
<button>
<slot></slot>
</button>
<slot name="41"></slot>
<slot name="42"></slot>
</div>
</template>
<style scoped>
</style>
Children
组件方便来调用具名插槽<script setup>
const props = defineProps({
msg: String
})
</script>
<template>
<div>
<div>我是子组件</div>
<div>传入的msg是{{ props.msg }}</div>
<div>我被当成一个插槽传入了</div>
</div>
</template>
<style scoped>
</style>
App.vue
中调用如下:<script setup>
import HelloWorld from './components/HelloWorld.vue'
import Children from './components/Children.vue';
</script>
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld>
我是按钮
<!-- 匿名插槽还可以写成下面这种形式
<template v-slot>
<div>我是匿名插槽</div>
</template> -->
<template #41>
<Children msg="我是41插槽"></Children>
</template>
<template #42>
<Children msg="我是42插槽"></Children>
</template>
</HelloWorld>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
#41
是v-slot:41
的缩写template
直接用的slot
import './App.css';
function Button () {
return <button></button>
}
function App () {
return (
<div className="App">
<Button>我是button</Button>
</div>
);
}
export default App;
React
实现一下匿名插槽我是按钮
为什么没有实现?
props.children
import './App.css';
function Button (props) {
const { children } = props
return <button>
{children}
</button>
}
function App () {
return (
<div className="App">
<Button>
我是按钮
</Button>
</div>
);
}
export default App;
我是按钮
就显示出来了react
会让人感觉很清爽React
来实现一下具名插槽import './App.css';
function Button (props) {
const { children, slotTop, slotBottom } = props
return <>
{slotTop()}
<button>
{children}
</button>
{slotBottom()}
</>
}
function slotTop () {
return <div>我是slotTop</div>
}
function slotBottom () {
return <div>我是slotBottom</div>
}
function App () {
return (
<div className="App">
<Button
slotTop={slotTop}
slotBottom={slotBottom}>
我是按钮
</Button>
</div>
);
}
export default App;
vue
和react
,谈谈感受react
的思维方式更加直接简约
react
这里实现的具名插槽有一些肤浅
vue
中插槽的值是通过template
传入的antd
的处理吧antd
的React
实现const kids =
children || children === 0
? spaceChildren(children, isNeedInserted() && autoInsertSpace)
: null;
if (linkButtonRestProps.href !== undefined) {
return (
<a {...linkButtonRestProps} className={classes} onClick={handleClick} ref={buttonRef}>
{iconNode}
{kids}
</a>
);
}
{kid}
可以看到上面还有一个{iconNode}
,具体是啥没仔细看kid
是上面的spaceChildren
函数来生成的,我们继续看一层function spaceChildren(children: React.ReactNode, needInserted: boolean) {
let isPrevChildPure: boolean = false;
const childList: React.ReactNode[] = [];
React.Children.forEach(children, child => {
const type = typeof child;
const isCurrentChildPure = type === 'string' || type === 'number';
if (isPrevChildPure && isCurrentChildPure) {
const lastIndex = childList.length - 1;
const lastChild = childList[lastIndex];
childList[lastIndex] = `${lastChild}${child}`;
} else {
childList.push(child);
}
isPrevChildPure = isCurrentChildPure;
});
// Pass to React.Children.map to auto fill key
return React.Children.map(childList, child =>
insertSpace(child as React.ReactChild, needInserted),
);
}
html
标签和组件
string
和number
就直接拼接到上一个children
childList
队列中,这个就应该可以理解为单个组件了不再深入探究了,各位道友可以指导一下,个人理解难免会有错误,希望大家批评指正!