react-router之Route渲染內(nèi)容的三種方式

react-router之Route渲染內(nèi)容的三種方式

結(jié)論: Route渲染優(yōu)先級(jí): children > component > render

component

  • 只有path匹配時(shí),組件才呈現(xiàn)。匹配user路徑則渲染UserPage
 <Route path="/user" component={UserPage} />

官方: When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).

翻譯: 當(dāng)你使用component(而不是render, children), router使用React.createElement從給定組件創(chuàng)建一個(gè)新的React元素。

這意味著如果您為組件道具提供內(nèi)聯(lián)函數(shù),那么您將在每次呈現(xiàn)時(shí)創(chuàng)建一個(gè)新組件。這將導(dǎo)致現(xiàn)有組件卸載和新組件掛載,而不只是更新現(xiàn)有組件。

當(dāng)使用內(nèi)聯(lián)函數(shù)進(jìn)行內(nèi)聯(lián)呈現(xiàn)時(shí),請(qǐng)使用render或children道具(下面)。

Render: func()

  • render可以方便地進(jìn)行內(nèi)聯(lián)呈現(xiàn)和包裝,而不需要進(jìn)行不必要的重新加載

官方: Instead of having a new React element created for you using the component prop, you can pass in a function to be called when the location matches. The render prop function has access to all the same route props (match, location and history) as the component render prop

翻譯: 不使用components屬性為您創(chuàng)建一個(gè)新的React元素,使用render您可以傳入一個(gè)函數(shù),以便在位置匹配時(shí)調(diào)用。渲染道具功能可以訪問(wèn)所有相同的路徑道具(match,location和history)作為組件渲染道具

案例

  • 給路由組件傳遞一個(gè)count屬性
// app.js
import React, { useState } from 'react'

import { BrowserRouter as Router, Link, Route } from 'react-router-dom'
import UserPage from './views/UserPage'
import HomePage from './views/HomePage'
import LoginPage from './views/LoginPage'

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <div>
        Count : {count}
        <button onClick={() => setCount(count + 1)}>我是按鈕</button>
      </div>
      <Router>
        <Link to="/">首頁(yè)</Link>
        <Link to="/user">用戶</Link>
        <Link to="/home">主頁(yè)</Link>
        <Link to="/login">登錄</Link>
     
          {/* component 屬性 */}   
      <Route path="/user" component={() => <UserPage count={count} />} />
      {/*  <Route path="/user" render={() => <UserPage count={count} />} /> */} 
        <Route
          path="/home"
          render={() => {
            console.log('homepage')
            return <HomePage />
          }}
        />
        <Route path="/login" children={LoginPage} />
      </Router>
    </div>
  )
}

export default App

  • 此時(shí)采用了component屬性, 傳遞count給UserPage
 <Route path="/user" component={() => <UserPage count={count} />} />
  • UserPage.js中展示
// userPage.js
import React, { PureComponent } from 'react'

class UserPage extends PureComponent {
  componentDidMount() {
    console.log('UserPage渲染了。。')
  }
  componentWillUnmount() {
    console.log('userPage卸載了。。。')
  }
  render() {
    // 掛載了 history: location match:三個(gè)對(duì)象
    console.log('UserPage prosp', this.props)
    return <div>UserPage == Count:{this.props.count}</div>
  }
}

export default UserPage
  • 點(diǎn)擊按鈕時(shí), 發(fā)生如下UserPage 重復(fù)渲染,
  • react在比較組件狀態(tài)以便決定如何更新dom節(jié)點(diǎn)時(shí),首先要比較組件的type和key。
  • 所以component使用內(nèi)聯(lián)函數(shù)時(shí), 會(huì)調(diào)用React.createElement創(chuàng)建元素,傳入時(shí)一個(gè)匿名函數(shù),組件每次都會(huì)生成一個(gè)新的匿名函數(shù),導(dǎo)致生成組件的type不相同, 造成組件的掛載,卸載現(xiàn)象
image-20201019155418455
  • 采用官方推薦方案,采用render寫(xiě)法, 內(nèi)聯(lián)函數(shù)
<Route path="/user" render={() => <UserPage count={count} />} />
image-20201019155826649

children: func

  • 不管是否存在匹配項(xiàng),childern都可以渲染一些東西,其他使用和render一樣
  • 修改為 children屬性
 <Route path="/user" children={() => <UserPage count={count} />} />
image-20201019162516501

Route核心渲染源碼

 return (
          <RouterContext.Provider value={props}>
              {match // 是否與地址匹配
                ? children // 1.優(yōu)先判斷children是否存在
                  ? typeof children === 'function' // 存在情況下判斷children是否是個(gè)函數(shù)
                    ? children(props)
                    : children
                  : component // 2.判斷是否是一個(gè)component,
                  ? React.createElement(component.props) // 是, 創(chuàng)建一個(gè)元素
                  : render // 3. 判斷是否是render屬性; render傳入是一個(gè)函數(shù)
                  ? render(props) // 執(zhí)行render
                  : null // 否, 輸出是空的
               
                : children // 不匹配,判斷是否是有children
                ? typeof children === 'function' // 判斷children是否是個(gè)函數(shù)
                  ? children(props) // 執(zhí)行函數(shù)
                  : children // 組件直接渲染
                : null}
            </RouterContext.Provider>
          )
     
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容