最近做了一个后台管理系统主体框架是基于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.routesthis.currentUrl; }; 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分为三类:
代码语言:javascript复制老浏览器的history: 主要通过hash来实现,对应createHashHistory,通过hash来存储在不同状态下的history信息
高版本浏览器: 通过html5里面的history,对应createBrowserHistory,利用HTML5里面的history
node环境下: 主要存储在memeory里面,对应createMemoryHistory,在内存中进行历史记录的存储
执行URL前进
代码语言:javascript复制createBrowserHistory: pushState、replaceState
createHashHistory: location.hash=*** location.replace()
createMemoryHistory: 在内存中进行历史记录的存储
执行URL回退
代码语言:javascript复制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