众所周知,目前单页面使用的路由有两种实现方式:
- hash 模式
- history 模式
hash 模式
路由原理:
我们先来看hash模式,页面首次加载时需要在load事件中解析初始的URL,从而展示进入的页面。当 # 后面的哈希值发生变化时,不会向服务器请求数据,可以通过 hashchange 事件来监听到 URL 的变化,从而进行跳转页面。
react代码实现:
1、使用react脚手架构建一个react的项目:
>npx creact-react-app my-app
2、创建两个组件 home.js 、 setting.js,使用hash路由来实现两个组件的切换。
项目目录如下:
3、在App.js文件中,我们需要实现如下的效果:
import React from 'react'import Home from './pages/home'import Setting from './pages/setting'import {Router, Route, Link} from './router'export default function App() { return ( 首页 设置 )}
整个结构使用Router组件包裹,由Route组件承载每一项路由的组件,由Link标签实现切换。那么我们来看一下router内部如何实现的。
4、先来看一下router文件夹的结构:
组件Router,Route,Link在router/Route.js,router/Route.js,route/Link.js三个文件中实现。router/index.js将三个组件集成方便外部调用。来看一下index.js的内容:
export {default as Router} from './Router'export {default as Route} from './Route'export {default as Link} from './Link'
5、整个路由项目被Router标签包裹,实际上需要达到共享路由当前地址的目的,借助react中的 context 来实现。同时Router组件需要在项目首次加载时解析当前的hash值,并且监听hash值的变化,根据hash值,来通知 children 当前的路由地址。代码如下:
import React, { Component, createContext } from "react";// 用于共享路由当前hash地址export const RouterContext = createContext();export default class Router extends Component { state = { path: "/",//路由当前hash地址 }; // 解析hash地址 getPath() { let path = window.location.hash; if (path) { path = path.replace("#", ""); } else { path = "/"; } this.setState({ path }); } componentDidMount() { // 先解析第一次的hash值 this.getPath(); // 监听之后hash值的变化,进入路由和返回 window.onhashchange = (ev) => { this.getPath(); }; } render() { // 使用context共享路由当前hash地址 return ( {this.props.children} ); }}
6、Route组件是根据当前的hash地址判断当前的Route承载的组件是否应该显示,代码如下:
import React, {useContext} from 'react'import {RouterContext} from './Router'export default function Route(props) { //获得当前hash地址 const context = useContext(RouterContext); return ( //当前的hash地址和组件配置的地址比较,相等就进入路由对应的组件,不想等则不显示组件。 context.path === props.path ? : null );}
注:如果需要实现路由嵌套和动态路由,当前的hash地址和组件配置的地址比较就不是使用===判断这么简单了,在这里我不做陈述,感兴趣的话可以自己研究一下。
7、Link组件只需要触发hash路由的切换。代码如下:
import React from 'react'export default function Link({to, children}) { //Link组件实现hash路由的切换,故只需要通过a标签切换hash值 return ( {children} )}
8、最后,我们来看一下显示效果: