最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React.cloneElement的使用詳解

 更新時間:2021年04月06日 10:33:24   作者:fullstackbb  
這篇文章主要介紹了React.cloneElement的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下

因為要接手維護(hù)一些項目,團(tuán)隊的技術(shù)棧最近從 vue 轉(zhuǎn)向 react ,作為一個 react 新手,加上一向喜歡通過源碼來學(xué)習(xí)新的東西,就選擇了通過閱讀 antd 這個大名鼎鼎的項目源碼來學(xué)習(xí)一些 react 的用法。

在閱讀源碼的過程中,發(fā)現(xiàn)好些組件都使用了 React.cloneElement 這個 api ,雖然通過名字可以猜測它做了什么,但是并不知道具體的作用;然后去看官方文檔,文檔很清晰地描述了它的作用,卻沒有告訴我們什么場景下需要使用它。于是我根據(jù)文檔的描述,結(jié)合源碼的使用,面向 google 和 stackoverflow,總結(jié)出來一些使用場景。

cloneElement 的作用

React.cloneElement(
 element,
 [props],
 [...children]
)

首先看一下官方文檔對這個 API 的描述:

Clone and return a new React element using element as the starting point. The resulting element will have the original element's props with the new props merged in shallowly. New children will replace existing children. key and ref from the original element will be preserved.

總結(jié)下來就是:

  1. 克隆原來的元素,返回一個新的 React 元素;
  2. 保留原始元素的 props,同時可以添加新的 props,兩者進(jìn)行淺合并;
  3. key 和 ref 會被保留,因為它們本身也是 props ,所以也可以修改;
  4. 根據(jù) react 的源碼,我們可以從第三個參數(shù)開始定義任意多的子元素,如果定義了新的 children ,會替換原來的 children ;

使用場景

根據(jù)上面的定義分解,我們可以在不同的場景下根據(jù)需要來使用這個 api 。

添加新的 props

當(dāng)我們創(chuàng)建一個通用組件時,根據(jù)內(nèi)部的邏輯,想要給每個子元素添加不同的類名,這個時候我們可以修改它的 className

假設(shè)我們有一個 Timeline 組件,允許我們根據(jù)需要定義多個 TimelineItem ,在內(nèi)部我們想要給最后一個TimelineItem 添加一個 timeline-item-last 類來渲染特殊的效果,這個時候我們可以這樣做:

const MyTimeline = () => {
 return (
  <Timeline>
   <TimelineItem>2020-06-01</TimelineItem>
   <TimelineItem>2020-06-08</TimelineItem>
   <TimelineItem>2020-07-05</TimelineItem>
  </Timeline>
 )
}

// 在 Timeline 內(nèi)部,邏輯可能是這樣的
import class from 'classnames';
const Timeline = props => {
 // ...
 // ...
 const itemCount = React.children.count(props.children);
 const items = React.children.map(props.children, (item, index) => {
  return React.cloneElement(item, {
   className: class([
    item.props.className,
    'timeline-item',
    index === count - 1 ? 'timeline-item-last' : ''
   ])
  })
 }
 return <div className={'timeline'}>{ items }</div>
}

除了添加 className ,還可以動態(tài)給子組件添加更多的 props 信息,react-router Switch 會給匹配的子組件添加 locationcomputedMatch 信息:

class Switch extends React.Component {
 render() {
  return (
   <RouterContext.Consumer>
    {context => {
     invariant(context, "You should not use <Switch> outside a <Router>");

     const location = this.props.location || context.location;

     let element, match;

     // We use React.Children.forEach instead of React.Children.toArray().find()
     // here because toArray adds keys to all child elements and we do not want
     // to trigger an unmount/remount for two <Route>s that render the same
     // component at different URLs.
     React.Children.forEach(this.props.children, child => {
      if (match == null && React.isValidElement(child)) {
       element = child;

       const path = child.props.path || child.props.from;

       match = path
        ? matchPath(location.pathname, { ...child.props, path })
        : context.match;
      }
     });

     return match
      ? React.cloneElement(element, { location, computedMatch: match })
      : null;
    }}
   </RouterContext.Consumer>
  );
 }
}

修改 props 的事件

假設(shè)我們有一個 Tab 組件,它下面包含多個 TabPane 子組件,我們想要點擊每個 TabPane 子組件的同時觸發(fā) Tab 的 onClick 事件,用戶自己本身可能給每個 TabPane 定義了獨立的 onClick 事件,這時候我們就要修改子組件 onClick 事件:

const Tab = props => {
 const { onClick } = props;
 const tabPanes = React.children.map(props.children, (tabPane, index) => {
  const paneClick = () => {
   onClick && onClick(index);
   tabPane.props?.onClick();
  }
  return React.cloneElement(tabPane, {
    onClick: paneClick,
  })
 })
 return <div>{ tabPanes }</div>
}

定制樣式

創(chuàng)建一個叫 FollowMouse 組件時,我們允許用戶定義內(nèi)容組件 Content ,當(dāng)鼠標(biāo)移動時,根據(jù)內(nèi)容的大小,自動計算 Content 的位置避免溢出屏幕,這個時候我們就可以使用 cloneElement 來動態(tài)修改它的樣式。

// 簡單起見,這里省略鼠標(biāo)事件。
const FollowMouse = props => {
 const { Content } = props;
 const customContent = React.isValidElement ? Content : <span>{ Content }</span>
 const getOffset = () => {
  return {
   position: 'absolute',
   top: ...,
   left: ...,
  }
 }
 const renderContent = React.cloneElement(custonContent, {
  style: {
   ...getOffset()
  }
 })
 return <div>{ renderContent() }</div>
}

添加 key

當(dāng)我們創(chuàng)建一個元素列表時,可以通過 cloneElement 給每個節(jié)點添加一個 key 。

const ComponentButton = props => {
 const { addonAfter, children } = props;
 const button = <button key='button'>{ children }</button>
 const list = [button, addonAfter ? React.cloneElement(addonAfter, { key: 'button-addon' } : null)
 return <div>{ list } <div>
}

總結(jié)

在開發(fā)復(fù)雜組件中,經(jīng)常會根據(jù)需要給子組件添加不同的功能或者顯示效果,react 元素本身是不可變的 (immutable) 對象, props.children 事實上并不是 children 本身,它只是 children 的描述符 (descriptor) ,我們不能修改任何它的任何屬性,只能讀到其中的內(nèi)容,因此 React.cloneElement 允許我們拷貝它的元素,并且修改或者添加新的 props 從而達(dá)到我們的目的。

當(dāng)然,得益于 react 強(qiáng)大的組合模式,這并不僅僅局限于 props.children ,不管是 props.left 還是 props.right 或者任何其它的 props 傳進(jìn)來的內(nèi)容,只要是合法的 react 元素,我們都可以使用這個 React.cloneElement 對其進(jìn)行操作。

以上就是React.cloneElement的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于React.cloneElement的使用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React事件處理過程中傳參的實現(xiàn)方法

    React事件處理過程中傳參的實現(xiàn)方法

    這篇文章主要介紹了React事件處理過程中傳參的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • Hello?React的組件化方式之React入門小案例演示

    Hello?React的組件化方式之React入門小案例演示

    這篇文章主要介紹了Hello?React的組件化方式-React入門小案例,本文通過Hello?React的案例,?來體驗一下React開發(fā)模式,?以及jsx的語法,需要的朋友可以參考下
    2022-10-10
  • 一文詳解React中如何處理高階組件中的錯誤

    一文詳解React中如何處理高階組件中的錯誤

    在?React?高階組件中處理錯誤是確保應(yīng)用程序健壯性和穩(wěn)定性的重要環(huán)節(jié),本文為大家整理了一些處理高階組件中錯誤的常見方法,需要的小伙伴可以參考下
    2025-02-02
  • React?如何向url中添加參數(shù)

    React?如何向url中添加參數(shù)

    這篇文章主要介紹了React?如何向url中添加參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 深入理解React中es6創(chuàng)建組件this的方法

    深入理解React中es6創(chuàng)建組件this的方法

    this的本質(zhì)可以這樣說,this跟作用域無關(guān)的,只跟執(zhí)行上下文有關(guān)。接下來通過本文給大家介紹React中es6創(chuàng)建組件this的方法,非常不錯,感興趣的朋友一起看看吧
    2016-08-08
  • ReactJS中的自定義組件實例代碼

    ReactJS中的自定義組件實例代碼

    React 是一個用于構(gòu)建用戶界面的 JAVASCRIPT 庫。這篇文章主要介紹了ReactJS中的自定義組件的代碼講解,需要的朋友可以參考下
    2019-11-11
  • react-redux及redux狀態(tài)管理工具使用詳解

    react-redux及redux狀態(tài)管理工具使用詳解

    Redux是為javascript應(yīng)用程序提供一個狀態(tài)管理工具集中的管理react中多個組件的狀態(tài)redux是專門作狀態(tài)管理的js庫(不是react插件庫可以用在其他js框架中例如vue,但是基本用在react中),這篇文章主要介紹了react-redux及redux狀態(tài)管理工具使用詳解,需要的朋友可以參考下
    2023-01-01
  • react?hooks頁面實時刷新方式(setInterval)

    react?hooks頁面實時刷新方式(setInterval)

    這篇文章主要介紹了react?hooks頁面實時刷新方式(setInterval),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • React通過父組件傳遞類名給子組件的實現(xiàn)方法

    React通過父組件傳遞類名給子組件的實現(xiàn)方法

    React 是一個用于構(gòu)建用戶界面的 JAVASCRIPT 庫。這篇文章主要介紹了React通過父組件傳遞類名給子組件的方法,需要的朋友可以參考下
    2017-11-11
  • 使用webpack5從0到1搭建一個react項目的實現(xiàn)步驟

    使用webpack5從0到1搭建一個react項目的實現(xiàn)步驟

    這篇文章主要介紹了使用webpack5從0到1搭建一個react項目的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論

丹棱县| 河津市| 邵东县| 青海省| 黎城县| 灵石县| 襄汾县| 司法| 宿迁市| 南昌县| 东台市| 句容市| 瓦房店市| 黎城县| 达孜县| 威海市| 玉山县| 巢湖市| 东丽区| 通江县| 伊金霍洛旗| 民县| 光泽县| 定西市| 中牟县| 房产| 华容县| 容城县| 淮滨县| 康保县| 黄梅县| 昌江| 廉江市| 丰台区| 象州县| 安新县| 鹤壁市| 金昌市| 天气| 鞍山市| 资溪县|