react後臺管理系統路由方案及react-router原理解析
最近做了一個後臺管理系統主體框架是基於React進行開發的,因此係統的路由管理,選用了react-router(4.3.1)外掛進行路由頁面的管理配置。
實現原理剖析
1、hash的方式
以 hash 形式(也可以使用 History API 來處理)為例,當 url 的 hash 發生變化時,觸發 hashchange 註冊的回撥,回撥中去進行不同的操作,進行不同的內容的展示
function Router() {undefined
this.routes = {};
this.currentUrl = ‘’;
}
Router.prototype.route = function(path, callback) {undefined
this.routes[path] = callback || function(){};
};
Router.prototype.refresh = function() {undefined
this.currentUrl = location.hash.slice(1) || ‘/’;
this.routes
};
Router.prototype.init = function() {undefined
window.addEventListener(‘load’, this.refresh.bind(this), false);
window.addEventListener(‘hashchange’, this.refresh.bind(this), false);
}
window.Router = new Router();
window.Router.init();
我們也可以自己進行模擬,可以寫成這樣:
function App() {undefined
// 進入頁面時,先初始化當前 url 對應的元件名
let hash = window.location.hash
let initUI = hash === ‘#login’ ? ‘login’ : ‘register’
let [UI, setUI] = useState(initUI);
let onClickLogin = () => {undefined
setUI(‘Login’)
window.location.hash = ‘login’
}
let onClickRegister = () => {undefined
setUI(‘Register’)
window.location.hash = ‘register’
}
let showUI = () => {undefined
switch(UI) {undefined
case ‘Login’:
return
case ‘Register’:
return
}
}
return (
Login
Register
{showUI()}
);
}
這樣其實已經滿足我們的要求了,如果我在位址列裡輸入 localhost:8080/#login,就會顯示 。但是這個 “#” 符號不太好看,如果輸入 localhost:8080/login 就完美了。
2、history的方式
H5 提供了一個好用的 history API,使用 window.history.pushState() 使得我們即可以修改 url 也可以不重新整理頁面,一舉兩得。現在只需要修改點選回撥裡的 window.location.pathname = ‘xxx’ 就可以了,用 window.history.pushState() 去代替。
function App() {undefined
// 進入頁面時,先初始化當前 url 對應的元件名
let pathname = window.location.pathname
let initUI = pathname === ‘/login’ ? ‘login’ : ‘register’
let [UI, setUI] = useState(initUI);
let onClickLogin = () => {undefined
setUI(‘Login’)
window.history.pushState(null, ‘’, ‘/login’)
}
let onClickRegister = () => {undefined
setUI(‘Register’)
window.history.pushState(null, ‘’, ‘/register’)
}
let showUI = () => {undefined
switch(UI) {undefined
case ‘Login’:
return
case ‘Register’:
return
}
}
return (
Login
Register
{showUI()}
);
}
3、link的實現
react-router依賴基礎—history,history是一個獨立的第三方js庫,可以用來相容在不同瀏覽器、不同環境下對歷史記錄的管理,擁有統一的API。具體來說裡面的history分為三類:
老瀏覽器的history: 主要通過hash來實現,對應createHashHistory,通過hash來儲存在不同狀態下的history資訊
高版本瀏覽器: 通過html5裡面的history,對應createBrowserHistory,利用HTML5裡面的history
node環境下: 主要儲存在memeory裡面,對應createMemoryHistory,在記憶體中進行歷史記錄的儲存
執行URL前進
createBrowserHistory: pushState、replaceState
createHashHistory: location.hash=*** location.replace()
createMemoryHistory: 在記憶體中進行歷史記錄的儲存
執行URL回退
createBrowserHistory: popstate
createHashHistory: hashchange
React元件為什麼會更新
其實無論是react-router. react-redux. 能夠使元件更新的根本原因,還是最後出發了setState函式;對於react-router,其實是對history原生物件的封裝,重新封裝了push函式,使得我們在push函式執行的時候,可以觸發在Router元件中元件裝載之前,執行了history.listener函式,該函式的主要作用就是給listeners陣列新增監聽函式,每次執行history.push的時候,都會執行listenrs陣列中新增的listener, 這裡的listener就是傳入的箭頭函式,功能是執行了Router元件的setState函式,Router執行了setState之後,會將當前url位址列對應的url傳遞下去,當Route元件匹配到該位址列的時候,就會渲染該元件,如果匹配不到,Route元件就返回null;
componentWillMount() {undefined
const { children, history } = this.props
更多內容請見原文,文章轉載自:https://blog.csdn.net/weixin_44519496/article/details/118522634