自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

React高階用法之Render Props

開發(fā)
最近會陸續(xù)分享我在使用React的過程總結(jié)的一些比較高階的使用方法,這些方法可以提升代碼的可復(fù)用性,也讓代碼看起來更加簡潔明晰。今天要講的是Render Props,很多人可能都知道react的這個特性,但在實際項目中不知道如何用起來。剛好這兩天的一個項目中用到了它,所以借機分享一下。

 什么是Render Props
“render prop”是指一種在React組件之間使用值為函數(shù)的prop共享代碼的技術(shù)

這個概念聽上去有點拗口,我們拆開了看它。

首先它本質(zhì)上是一個prop,是用來父子組件之間傳遞數(shù)據(jù)用的
其次這個prop傳遞的值是一個函數(shù)
最后它取名render props,是因為它通常是用來render(渲染)某個元素或組件
比如官網(wǎng)給出的示例:

 

  1. <DataProvider render={data => ( 
  2.   <h1>Hello {data.target}</h1> 
  3. )}/> 

我們給 這個子組件傳遞了一個叫 render 的prop,這個prop的值是一個函數(shù),它返回了一個 h1 元素。然后我們可以假裝實現(xiàn)一下這個 組件:

 

  1. class DataProvider extends React.Component { 
  2.     state = { 
  3.         data: { 
  4.             target: 'World' 
  5.         } 
  6.     } 
  7.     render() { 
  8.         return this.props.render(this.state) 
  9.     } 

最終我們的 DataProvider 組件渲染的結(jié)果就是 <h1>Hello World</h1> 。有同學(xué)可能會有疑問,為什么要費這么大周折?直接把 h1 元素寫在 DataProvider 組件里不也可以嗎?

這里就要講到代碼的可復(fù)用性了,假如下次我們希望 DataProvider 組件渲染的結(jié)果就是 Hello World 呢?難道又去修改 DataProvider 組件嗎?有了render props,我們就可以動態(tài)地決定 DataProvider 組件內(nèi)部要渲染的元素,同時這個元素還可以使用到 DataProvider 組件內(nèi)部的數(shù)據(jù)。

實際項目案例
下面講一個實際的項目案例,下圖中我們有一個橫向滾動的 ScrollView 組件,這個組件本身是個很普通的

元素, 只不過樣式上加了 overflow-x: scroll 所以可以橫向滾動起來。產(chǎn)品同學(xué)說滾動區(qū)域的下方要有進度點指示,從而告訴用戶總共有幾個產(chǎn)品,已經(jīng)現(xiàn)在滾到第幾個產(chǎn)品了。

 

明確了產(chǎn)品需求以后,我們就開始來實現(xiàn),首先看下第一版:

 

  1. class demo extends Component { 
  2.     state = { 
  3.       activeIndicator: 0, 
  4.       list: [] 
  5.     } 
  6.      
  7.     onScroll = () => { 
  8.         const { list } = this.state; 
  9.         const container = findDOMNode(this.refs.container); 
  10.         ... 
  11.         const itemVisibleLengthInContainer = list.map((item, index) => { 
  12.           const node = findDOMNode(this.refs[`item-${index}`]); 
  13.            ... 
  14.         }); 
  15.         this.setState({ 
  16.           activeIndicator: active, 
  17.         }); 
  18.     }; 
  19.      
  20.     render() { 
  21.         const { list, activeIndicator } = this.state; 
  22.         return ( 
  23.              <ScrollView 
  24.                 ref="container" 
  25.                 horizontal={true
  26.                 onScroll={this.onScroll} 
  27.              > 
  28.                 {list.map((item,i) => ( 
  29.                     <ProductItem 
  30.                         ref={`item-${i}`} 
  31.                         data={item} 
  32.                     /> 
  33.                  ))} 
  34.                   
  35.              </ScrollView> 
  36.              <Indicator list={list} active={activeIndicator} /> 
  37.         ) 
  38.     } 

ok,需求我們已經(jīng)實現(xiàn)了。實現(xiàn)邏輯就是給 ScrollView 組件添加一個 onScroll 事件,每當滾動的時候,會先計算 ScrollView 容器的位置信息,和每一個 ProductItem 的位置信息,算出現(xiàn)在哪個 ProductItem 在 ScrollView 容器中所占比例最高,從而得出現(xiàn)在應(yīng)該高亮的 activeIndicator 。

不過現(xiàn)在有個問題哦,給 ScrollView 組件增加進度指示器這個功能,更像是 ScrollView 組件應(yīng)該支持的一個功能,而不是直接寫在業(yè)務(wù)代碼里。所以我們應(yīng)該提供一個新組件 ScrollViewWithIndicator ,讓它去處理進度指示器的問題,從而跟業(yè)務(wù)解耦。

 

  1. class ScrollViewWithIndicator extends Component { 
  2.     state = { 
  3.       activeIndicator: 0, 
  4.     } 
  5.      
  6.     onScroll = () => { 
  7.         const { list } = this.props; 
  8.         const container = findDOMNode(this.refs.container); 
  9.         ... 
  10.         const itemVisibleLengthInContainer = list.map((item, index) => { 
  11.           const node = findDOMNode(this.refs[`item-${index}`]); 
  12.            ... 
  13.         }); 
  14.         this.setState({ 
  15.           activeIndicator: active, 
  16.         }); 
  17.     }; 
  18.      
  19.     render() { 
  20.         const [{ list, children, ...restProps } , { activeIndicator }] = [this.props, this.state]; 
  21.         return ( 
  22.              <ScrollView 
  23.                 ref="container" 
  24.                 {...restProps} 
  25.                 onScroll={this.onScroll} 
  26.              > 
  27.                 {list.map((item,i) => ( 
  28.                     <div ref={`item-${i}`}>    
  29.                         {children(item} 
  30.                     </div> 
  31.                  ))} 
  32.                   
  33.              </ScrollView> 
  34.              <Indicator list={list} active={activeIndicator} /> 
  35.         ) 
  36.     } 

然后我們的業(yè)務(wù)代碼就可以簡化了:

 

  1. class demo extends Component { 
  2.     state = { 
  3.       list: [] 
  4.     } 
  5.     render() { 
  6.         const { list } = this.state; 
  7.         return ( 
  8.               <ScrollViewWithIndicator 
  9.                 horizontal={true
  10.                 list={list} 
  11.              > 
  12.               {child => <ProductItem {...child} />}  //(*) 
  13.              </ScrollViewWithIndicator> 
  14.         ) 
  15.     } 

仔細看業(yè)務(wù)代碼demo組件,我們一共給ScrollViewWithIndicator組件傳遞了多少個props?答案是三個!分別是horizontal, list ,children,大家千萬別忘了this.props.children也是一個props哦

再仔細看第(*)這句話,我們給ScrollViewWithIndicator組件傳遞一個叫children的prop,同時這個prop是一個函數(shù),返回了一個組件(元素),這就是我們所說的render props啊

為什么list.map這個數(shù)組的遍歷要寫在ScrollViewWithIndicator組件內(nèi)部,而不是業(yè)務(wù)組件demo里呢?因為我們在onScroll 事件回調(diào)函數(shù)里要計算每一個商品item的位置,也就是要拿到商品item的ref屬性,所以把數(shù)組的遍歷寫在ScrollViewWithIndicator 組件內(nèi)部方便我們顯性給每一個商品item聲明ref屬性

 

責任編輯:姜華 來源: 晨曦大前端
相關(guān)推薦

2020-10-25 07:49:37

React組件

2020-10-27 09:50:06

Reactrende前端

2024-06-05 08:29:35

2017-05-16 15:32:15

2024-06-14 07:47:37

2021-09-01 18:42:57

React Props組件

2016-08-12 13:55:06

2019-10-28 09:11:53

MySQL性能優(yōu)化

2025-03-06 11:07:27

2021-08-02 08:34:20

React性能優(yōu)化

2021-07-07 08:36:45

React應(yīng)用場景

2020-06-22 15:41:20

IF函數(shù)Excel用法

2023-11-01 17:57:56

React應(yīng)用程序性能

2022-03-16 17:01:35

React18并發(fā)的React組件render

2020-12-20 10:02:17

ContextReactrender

2023-04-20 10:15:57

React組件Render

2022-08-04 08:17:27

React高階組件

2024-06-21 09:44:52

.NET配置文件NuGet 包

2019-10-29 15:28:40

Refs組件前端

2024-02-01 00:10:21

C++PIMPL編程
點贊
收藏

51CTO技術(shù)棧公眾號