随着单页应用的发展,路由这个词不断出如今咱们的视线中,路由跳转,嵌套路由,路由配置,路由懒加载等等,目前整理了业界的一些面试题,带着问题去整理咱们须要学习的知识,面试题主要是react技术栈的,以下html
window.location.hash = 'product' // 设置 url 的 hash,会在当前url后加上 '#product' console.log(window.location.hash) // '#product' // 监听hash变化,点击浏览器的前进后退会触发 window.addEventListener('hashchange', function(){ }) // 或者在body上加上onhashchange <body onhashchange="myFunction()">
Hash history 使用 URL 中的 hash(#)部分去建立形如 example.com/#/some/path 的路由。前端
History 接口容许操做浏览器的曾经在标签页或者框架里访问的会话历史记录(相似栈对象)。经常使用Api以下html5
前往上一页, 用户可点击浏览器左上角的返回按钮模拟此方法. 等价于 history.go(-1).react
在浏览器历史记录里前往下一页,用户可点击浏览器左上角的前进按钮模拟此方法. 等价于 history.go(1).git
经过当前页面的相对位置从浏览器历史记录( 会话记录 )加载页面。github
按指定的名称和URL(若是提供该参数)将数据push进会话历史栈,数据被DOM进行不透明处理;面试
附加window apitypescript
window.onpopstate是popstate事件在window对象上的事件处理程序.
每当处于激活状态的历史记录条目发生变化时,popstate事件就会在对应window对象上触发. 若是当前处于激活状态的历史记录条目是由history.pushState()方法建立,或者由history.replaceState()方法修改过的, 则popstate事件对象的state属性包含了这个历史记录条目的state对象的一个拷贝. npm
调用history.pushState()或者history.replaceState()不会触发popstate事件. popstate事件只会在浏览器某些行为下触发, 好比点击后退、前进按钮(或者在JavaScript中调用history.back()、history.forward()、history.go()方法).redux
目前咱们是基于create-react-app脚手架搭建起来的项目简单配置的,直接上代码
npx create-react-app my-app --typescript npm install --save react-router-dom
declare module "react-router-dom";
// Layout.tsx import * as React from "react"; import RouteView, { IRouteViewProps } from "../routes/RouteView"; import { History } from "history"; interface ILayoutProps extends IRouteViewProps { history: History; } const Layout = (props: ILayoutProps) => { const handleClick = React.useCallback((e) => { const { name } = e.target; props.history.push(name); }, [props.history]); return ( <div> <div> <button name="/basic/page1" onClick={handleClick}> Page1 </button> <button name="/basic/page2" onClick={handleClick}> Page2 </button> <button name="/basic/page3" onClick={handleClick}> Page3 </button> </div> <RouteView {...props} /> </div> ); }; export default Layout; // Page1.tsx import * as React from "react"; const Page1 = () => { return ( <div>我是Page1</div> ) }; export default Page1; // Page2.tsx import * as React from "react"; const Page2 = () => { return ( <div>我是Page2</div> ) }; export default Page2; // Page3.tsx import * as React from "react"; const Page3 = () => { return ( <div>我是Page3</div> ) }; export default Page3;
// router.config.ts import Layout from "../pages/Layout"; import { lazy } from "react"; const RouteConfig = [ { path: "/basic", component: Layout, children: [ { path: "/basic/page1", component: lazy(() => import("../pages/Page1")), }, { path: "/basic/page2", component: lazy(() => import("../pages/Page2")), }, { path: "/basic/page3", component: lazy(() => import("../pages/Page3")), }, { path: "/basic", redirect: "/basic/page1" }, ], }, // { // path: "/login", // component: lazy(() => import("../pages/Login")), // }, { path: "/", redirect: "/basic", }, ]; export default RouteConfig; // RouteView.tsx import React from "react"; import { Redirect, Route, Switch } from "react-router-dom"; export interface IRouteViewProps { path?: string; redirect?: string; component?: any; children?: IRouteViewProps[]; } const RouteView = (props: IRouteViewProps) => { return ( <Switch> {props.children && props.children.map((item, index) => { if (item.redirect) { return ( <Redirect key={index} from={item.path} to={item.redirect} ></Redirect> ); } return ( <Route key={index} path={item.path} render={(props) => { return ( item.component && ( <item.component children={item.children} {...props} ></item.component> ) ); }} ></Route> ); })} </Switch> ); }; export default RouteView;
// App.tsx import React, { Suspense } from "react"; import RouteConfig from "./routes/router.config"; import RouteView from "./routes/RouteView"; import { BrowserRouter } from "react-router-dom"; const App = () => { return ( <BrowserRouter> <Suspense fallback={<div>loading...</div>}> <RouteView children={RouteConfig}></RouteView> </Suspense> </BrowserRouter> ); }; export default App;
一个具有路由嵌套,路由懒加载,可配置化的的React-Router就配置好了,代码请参考:https://github.com/wwlh200/re...
const {history} = props; history.push("/basic/product");
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(Product)); const {history} = props; history.push("/basic/other");
import { useHistory } from "react-router-dom"; function HomeButton() { let history = useHistory(); function handleClick() { history.push("/home"); } return ( <button type="button" onClick={handleClick}> Go home </button> ); }
const Component = React.lazy(() => import('./Component'));
缺点:不支持服务端渲染
// 第一步 npm install @loadable/component // 第二步 const Component = loadable(() => import('./Component'));
缺点:须要引入第三方包
import Loadable from "react-loadable"; export default function asyncComponent(comp) { return Loadable({ loader: comp, loading: (props) => { return "加载中..."; }, }); } import asyncComponent from "../utils/utils"; const Component = asyncComponent(() => import('./Component'));
缺点:该方法不建议使用,StrictMode下回报以下警告: The old API will be supported in all 16.x releases, but applications using it should migrate to the new version.