欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React元素與組件的區(qū)別示例詳解

 更新時(shí)間:2022年11月07日 08:56:34   作者:冴羽  
這篇文章主要為大家介紹了React元素與組件的區(qū)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

從問(wèn)題出發(fā)

我被問(wèn)過(guò)這樣一個(gè)問(wèn)題:

想要實(shí)現(xiàn)一個(gè) useTitle 方法,具體使用示例如下:

function Header() {
    const [Title, changeTitle] = useTitle();
    return (
        <div onClick={() => changeTitle('new title')}>
          <Title />
        </div>
    )
}

但在編寫(xiě) useTitle 代碼的時(shí)候卻出了問(wèn)題:

function TitleComponent({title}) {
    return <div>{title}</div>
}
function useTitle() {
    const [title, changeTitle] = useState('default title');
    useEffect(() => {
	changeTitle(title)
    }, [title])
    const Element = React.createElement(TitleComponent, {title});
    return [Element.type, changeTitle];
}

這段代碼直接報(bào)錯(cuò),連渲染都渲染不出來(lái),如果是你,該如何修改這段代碼呢?

元素與組件

其實(shí)這就是一個(gè)很典型的元素與組件如何區(qū)分和使用的問(wèn)題。

元素

我們先看 React 官方文檔中對(duì) React 元素的介紹

Babel 會(huì)把 JSX 轉(zhuǎn)譯成一個(gè)名為 React.createElement() 函數(shù)調(diào)用。以下兩種示例代碼完全等效:

const element = <h1 className="greeting">Hello, world!</h1>;
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement() 會(huì)預(yù)先執(zhí)行一些檢查,以幫助你編寫(xiě)無(wú)錯(cuò)代碼,但實(shí)際上它創(chuàng)建了一個(gè)這樣的對(duì)象:

// 注意:這是簡(jiǎn)化過(guò)的結(jié)構(gòu)
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

這些對(duì)象被稱為 “React 元素”。它們描述了你希望在屏幕上看到的內(nèi)容。

你看,React 元素其實(shí)就是指我們?nèi)粘>帉?xiě)的 JSX 代碼,它會(huì)被 Babel 轉(zhuǎn)義為一個(gè)函數(shù)調(diào)用,最終得到的結(jié)果是一個(gè)描述 DOM 結(jié)構(gòu)的對(duì)象,它的數(shù)據(jù)結(jié)構(gòu)本質(zhì)是一個(gè) JS 對(duì)象。

在 JSX 中,我們是可以嵌入表達(dá)式的,就比如:

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

所以如果我們要使用一個(gè) React 元素,那我們應(yīng)該使用嵌入表達(dá)式這種方式:

const name = <span>Josh Perez</span>;
const element = <h1>Hello, {name}</h1>;

組件

那組件呢?組件有兩種,函數(shù)組件和 class 組件:

// 函數(shù)組件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
// class 組件
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

那如何使用組件呢?

const element = <Welcome name="Sara" />;

對(duì)于組件,我們要使用類似于 HTML 標(biāo)簽的方式進(jìn)行調(diào)用,Babel 會(huì)將其轉(zhuǎn)譯為一個(gè)函數(shù)調(diào)用

const element = React.createElement(Welcome, {
  name: "Sara"
});

所以你看,組件的數(shù)據(jù)結(jié)構(gòu)本質(zhì)是一個(gè)函數(shù)或者類,當(dāng)你使用元素標(biāo)簽的方式進(jìn)行調(diào)用時(shí),函數(shù)或者類會(huì)被執(zhí)行,最終返回一個(gè) React 元素。

問(wèn)題如何解決

盡管這些內(nèi)容都來(lái)自于 React 官方文檔,但如果你能清晰的了解到 React 元素和組件的差別,你已經(jīng)可以解決開(kāi)頭的問(wèn)題了。至少有兩種方式可以解決,一種是返回 React 元素,一種是返回 React 組件

第一種我們返回 React 元素:

const root = ReactDOM.createRoot(document.getElementById('root'));
function Header() {
    const [Title, changeTitle] = useTitle();
    // 這里因?yàn)榉祷氐氖?React 元素,所以我們使用 {} 的方式嵌入表達(dá)式
    return (
        <div onClick={() => changeTitle('new title')}>
          {Title}
        </div>
    )
}
function TitleComponent({title}) {
    return <div>{title}</div>
}
function useTitle() {
    const [title, changeTitle] = useState('default title');
    useEffect(() => {
	changeTitle(title)
    }, [title])
    // createElement 返回的是 React 元素
    const Element = React.createElement(TitleComponent, {title});
    return [Element, changeTitle];
}
root.render(<Header />);

第二種我們返回 React 組件:

const root = ReactDOM.createRoot(document.getElementById('root'));
function Header() {
    const [Title, changeTitle] = useTitle();
    // 因?yàn)榉祷氐氖?React 組件,所以我們使用元素標(biāo)簽的方式調(diào)用
    return (
        <div onClick={() => changeTitle('new title')}>
          <Title />
        </div>
    )
}
function TitleComponent({title}) {
    return <div>{title}</div>
}
function useTitle() {
    const [title, changeTitle] = useState('default title');
    useEffect(() => {
	changeTitle(title)
    }, [title])
    // 這里我們構(gòu)建了一個(gè)函數(shù)組件
    const returnComponent = () => {
    	return <TitleComponent title={title} />
    }
    // 這里我們直接將組件返回出去
    return [returnComponent, changeTitle];
}
root.render(<Header />);

自定義內(nèi)容

有的時(shí)候我們需要給組件傳入一個(gè)自定義內(nèi)容。

舉個(gè)例子,我們實(shí)現(xiàn)了一個(gè) Modal 組件,有確定按鈕,有取消按鈕,但 Modal 展示的內(nèi)容為了更加靈活,我們提供了一個(gè) props 屬性,用戶可以自定義一個(gè)組件傳入其中,用戶提供什么,Modal 就展示什么,Modal 相當(dāng)于一個(gè)容器,那么,我們?cè)撛趺磳?shí)現(xiàn)這個(gè)功能呢?

第一種實(shí)現(xiàn)方式

以下是第一種實(shí)現(xiàn)方式:

function Modal({content}) {
  return (
    <div>
      {content}
      <button>確定</button>
      <button>取消</button>
    </div>
  )
}
function CustomContent({text}) {
  return <div>{text}</div>
}
<Modal content={<CustomContent text="content" />} />

根據(jù)前面的知識(shí),我們可以知道,content 屬性這里傳入的其實(shí)是一個(gè) React 元素,所以 Modal 組件的內(nèi)部是用 {} 進(jìn)行渲染。

第二種實(shí)現(xiàn)方式

但第一種方式,并不總能解決需求。有的時(shí)候,我們可能會(huì)用到組件內(nèi)部的值。

就比如一個(gè)倒計(jì)時(shí)組件 Timer,依然提供了一個(gè)屬性 content,用于自定義時(shí)間的展示樣式,時(shí)間由 Timer 組件內(nèi)部處理,展示樣式則完全由用戶自定義,在這種時(shí)候,我們就可以選擇傳入一個(gè)組件:

function Timer({content: Content}) {
    const [time, changeTime] = useState('0');
    useEffect(() => {
        setTimeout(() => {
            changeTime((new Date).toLocaleTimeString())
	}, 1000)
    }, [time])
    return (
        <div>
          <Content time={time} />
        </div>
    )
}
function CustomContent({time}) {
    return <div style={{border: '1px solid #ccc'}}>{time}</div>
}
<Timer content={CustomContent} />

在這個(gè)示例中,我們可以看到 content 屬性傳入的是一個(gè) React 組件 CustomContent,而 CustomContent 組件會(huì)被傳入 time 屬性,我們正是基于這個(gè)約定進(jìn)行的 CustomContent 組件的開(kāi)發(fā)。

而 Timer 組件內(nèi)部,因?yàn)閭魅氲氖墙M件,所以使用的是 <Content time={time}/>進(jìn)行的渲染。

第三種實(shí)現(xiàn)方式

在面對(duì)第二種實(shí)現(xiàn)方式的需求時(shí),除了上面這種實(shí)現(xiàn)方式,還有一種稱為 render props 的技巧,比第二種方式更常見(jiàn)一些,我們依然以 Timer 組件為例:

function Timer({renderContent}) {
    const [time, changeTime] = useState('0');
    useEffect(() => {
        setTimeout(() => {
            changeTime((new Date).toLocaleTimeString())
	}, 1000)
    }, [time])
  // 這里直接調(diào)用傳入的 renderContent 函數(shù)
    return (
        <div>
          {renderContent(time)}
        </div>
    )
}
function CustomContent({time}) {
    return <div style={{border: '1px solid #ccc'}}>{time}</div>
}
root.render(<Timer renderContent={(time) => {
    return <CustomContent time={time} />
}} />);

鑒于我們傳入的是一個(gè)函數(shù),我們把 content 屬性名改為了 renderContent,其實(shí)叫什么都可以。

renderContent 傳入了一個(gè)函數(shù),該函數(shù)接收 time 作為參數(shù),返回一個(gè) React 元素,而在 Timer 內(nèi)部,我們直接執(zhí)行了 renderContent 函數(shù),并傳入內(nèi)部處理好的 time 參數(shù),由此實(shí)現(xiàn)了用戶使用組件內(nèi)部值自定義渲染內(nèi)容。

多說(shuō)一句,除了放到屬性里,我們也可以放到 children 里,是一樣的:

function Timer({children}) {
  	// ...
    return (
        <div>
          {children(time)}
        </div>
    )
}
<Timer>
  {(time) => {
    return <CustomContent time={time} />
  }}
</Timer>

我們可以視情況選擇合適的傳入方法。

React 系列

React 之 createElement 源碼解讀

以上就是React元素與組件的區(qū)別示例詳解的詳細(xì)內(nèi)容,更多關(guān)于React元素組件區(qū)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React-router4路由監(jiān)聽(tīng)的實(shí)現(xiàn)

    React-router4路由監(jiān)聽(tīng)的實(shí)現(xiàn)

    這篇文章主要介紹了React-router4路由監(jiān)聽(tīng)的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • React獲取Java后臺(tái)文件流并下載Excel文件流程解析

    React獲取Java后臺(tái)文件流并下載Excel文件流程解析

    這篇文章主要介紹了React獲取Java后臺(tái)文件流下載Excel文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法

    react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法

    本篇文章主要介紹了react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 詳解React項(xiàng)目的服務(wù)端渲染改造(koa2+webpack3.11)

    詳解React項(xiàng)目的服務(wù)端渲染改造(koa2+webpack3.11)

    本篇文章主要介紹了詳解React項(xiàng)目的服務(wù)端渲染改造(koa2+webpack3.11),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 解析React中useMemo與useCallback的區(qū)別

    解析React中useMemo與useCallback的區(qū)別

    這篇文章主要介紹了React中useMemo與useCallback的區(qū)別,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • React?useEffect不支持async?function示例分析

    React?useEffect不支持async?function示例分析

    這篇文章主要為大家介紹了React?useEffect不支持async?function示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • React組件useReducer的講解與使用

    React組件useReducer的講解與使用

    在React函數(shù)式組件中,我們可以通過(guò)useState()來(lái)創(chuàng)建state,這種state創(chuàng)建方式會(huì)給我們返回兩個(gè)東西state和setState()。
    2023-04-04
  • 手把手教您實(shí)現(xiàn)react異步加載高階組件

    手把手教您實(shí)現(xiàn)react異步加載高階組件

    這篇文章主要介紹了手把手教您實(shí)現(xiàn)react異步加載高階組件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • React傳值 組件傳值 之間的關(guān)系詳解

    React傳值 組件傳值 之間的關(guān)系詳解

    這篇文章主要介紹了React傳值 組件傳值 之間的關(guān)系詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • React之PureComponent的使用作用

    React之PureComponent的使用作用

    這篇文章主要介紹了React之PureComponent的使用作用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07

最新評(píng)論