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

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

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

component

  • 只有path匹配時,組件才呈現(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)建一個新的React元素。

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

當(dāng)使用內(nèi)聯(lián)函數(shù)進(jìn)行內(nèi)聯(lián)呈現(xiàn)時,請使用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)建一個新的React元素,使用render您可以傳入一個函數(shù),以便在位置匹配時調(diào)用。渲染道具功能可以訪問所有相同的路徑道具(match,location和history)作為組件渲染道具

案例

  • 給路由組件傳遞一個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="/">首頁</Link>
        <Link to="/user">用戶</Link>
        <Link to="/home">主頁</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

  • 此時采用了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:三個對象
    console.log('UserPage prosp', this.props)
    return <div>UserPage == Count:{this.props.count}</div>
  }
}

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

children: func

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

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