首先 導航連接應該使用 NavLink 而再也不是 Link html
NavLink 使用方法見 https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/NavLink.mdreact
NavLink 和 PureComponent 一塊兒使用的時候,會出現 激活連接樣式(當前頁面對應連接樣式,經過 activeClassName、activeStyle 設置) 不生效的狀況。效果以下:git
刷新頁面後導航激活樣式生效,點擊導航連接的時候 url 跳轉,可是導航激活樣式不生效。github
上圖效果對應代碼:api
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>NavLink And PureComponent</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> <script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script> <style> .menu-link { display: inline-block; width: 100px; text-decoration: none; text-align: center; background: #dedede; } .menu-link.active { background: tomato; } </style> </head> <body> <div id="app"></div> <script type="text/babel"> // import ReactRouterDOM, { HashRouter, Route } from 'react-router-dom'; // import React, { Component, PureComponent } from 'react'; const { HashRouter, Route, NavLink } = ReactRouterDOM; const { Component, PureComponent } = React; class Menu extends PureComponent { render() { return ( <div> <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/home'>首頁</NavLink> <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/help'>幫助頁</NavLink> </div> ); } } class App extends PureComponent { render() { return ( <HashRouter> <div> <Menu /> <Route path='/home' component={ () => <div>首頁內容</div> } /> <Route path='/help' component={ () => <div>幫助頁內容</div> } /> </div> </HashRouter> ); } } ReactDOM.render( <App />, document.getElementById('app') ); </script> </body> </html>
爲何不生效,咱們在使用 PureComponent 以前應該知道 它至關於對組件的 props 和 state 進行淺比較,若是相等則不更新,以此來進行優化,防止多餘更新。babel
而在上面的例子中 就至關於react-router
class Menu extends Component { shouldComponentUpdate(props, state) { console.log(props, this.props, props === this.props); // {} {} true console.log(state, this.state, state === this.state); // null null true // 因爲 props 和 state 都不發生變化 下面的表達式會返回 false 組件不會發生更新 return !shallowEqual(props, this.props) || !shallowEqual(state, this.state); } render() { return ( <div> <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/home'>首頁</NavLink> <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/help'>幫助頁</NavLink> </div> ); } }
其中淺比較函數 shallowEqual 的實現(https://blog.csdn.net/juzipidemimi/article/details/80892440)app
function is(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 // Added the nonzero y check to make Flow happy, but it is redundant,排除 +0 === -0的狀況 return x !== 0 || y !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN,x和y都不是NaN return x !== x && y !== y; } } function shallowEqual(objA, objB) { if (is(objA, objB)) { return true; } if ( typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null ) { return false; } const keysA = Object.keys(objA); const keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } // Test for A's keys different from B. for (let i = 0; i < keysA.length; i++) { if ( !hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]]) ) { return false; } } return true; }
因此組件 Menu 不會發生更新,因此其子組件 NavLink 天然也就不會被更新。dom
那麼該若是解決這個問題呢?ide
最簡單的固然就是使用 Component 替換 PureComponent
若是不想更改 PureComponent 的話,能夠經過給組件傳入當前 location 做爲屬性來解決。
NavLink 是經過監聽當前所在 location 來更新連接樣式的,因此若是能在 location 改變的時候,更新組件就能夠了,而作到這一點,只須要把 location 做爲一個屬性傳入組件。
最簡單的辦法,把導航組件也做爲一個 Route,而且能動態匹配全部路徑,這樣 location 會自動做爲屬性被注入到組件。
class App extends PureComponent { render() { return ( <HashRouter> <div> <Route path="/:place" component={Menu} /> <Route path='/home' component={ () => <div>首頁內容</div> } /> <Route path='/help' component={ () => <div>幫助頁內容</div> } /> </div> </HashRouter> ); } }
全文參考: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md
若是能幫助到你,點個讚唄 😂