React实现类Vue中的v-slot作用域

326 阅读2分钟

今天发现了React组件的奇葩使用方式,一时间仿佛打开了新世界的大门,脑海中灵感蜂拥而至。结果,啥也没抓住。。。

image.png

事情是这样的,正常我们对一个组件的引入是这样的

image.png

显而易见的,浏览器上出现了一个大大的A。然后我换了一种写法

image.png

纳尼!浏览器上还是能显示一个大大的A,我惊呆了,这是什么神仙操作。

大家可能会说,ComponentA本身就是个函数,函数加括号调用不是很正常吗?

image.png

然后我灵感就来了,既然可以用函数调用的方式使用,那组件的参数不就可以通过函数传参的方式传递了。

正规的传参方式

image.png

当参数多的时候写起来总感觉不顺畅。

然后使用不正规的传参方式

image.png

当组件参数已经封装在页面对象的时候,直接整个对象往组件函数里一传,这感觉,妙~ 啊~

说时迟,那时快。又一个想法钻进了我的脑海中。

Vue的Slot插槽中,子组件可以获取父组件传递的属性。用函数调用的方式React好像也可以。走~搞起

假设现在有两个列表如下

image.png

它们除了序号方式、背景颜色之外其他都一样。如果将列表项抽离出来,背景颜色由父级元素控制,那我集齐一套彩虹色列表就指日可待了。

最终代码实现如下:

function ListItem({text, style}: {text: string; style: object}) {
  return <li key={text} style={style}>{text}</li>
}

const UlList:React.FC<{data: number[], item: Function}> = ({data, item}) => {
  return <ul style={{width: '100px'}}>
    {data.map(i => {
      const IStyle = i%2 === 0 ? {background: '#fff566'} : {background: '#40a9ff'}
      return item({text: i, style: IStyle});
    })}
  </ul>;
}

const OlList:React.FC<{data: number[], item: Function}> = ({data, item}) => {
  return <ol style={{width: '100px'}}>
    {data.map(i => {
      const IStyle = i%2 === 0 ? {background: '#36cfc9'} : {background: '#d3f261'}
      return item({text: i, style: IStyle});
    })}
  </ol>;
}


function App() {
  const data = Array(10).fill(true).map((_, i) => i);
  return (
    <div className="App">
      <UlList data={data} item={ListItem}></UlList>
      <OlList data={data} item={ListItem}></OlList>
    </div>

  )
}

也可以使用children进行传递

function ListItem({text, style}: {text: string; style: object}) {
  return <li key={text} style={style}>{text}</li>
}

const UlList:React.FC<{data: number[]}> = ({data, children}) => {
  return <ul style={{width: '100px'}}>
    {data.map(i => {
      const IStyle = i%2 === 0 ? {background: '#fff566'} : {background: '#40a9ff'}
      return (children as Function)?.({text: i, style: IStyle});
    })}
  </ul>;
}

function App() {
  const data = Array(10).fill(true).map((_, i) => i);
  return (
    <div className="App">
      <UlList data={data}>
        {ListItem}
      </UlList>
    </div>
  )
}

感觉自己棒棒哒!!!

image.png

有其他更好的想法、思路欢迎留言讨论~~