美文网首页React
react-router > 4.0 路由

react-router > 4.0 路由

作者: CondorHero | 来源:发表于2020-05-05 12:30 被阅读0次

    一、如何找到文档

    在 GitHub 上直接搜索 react-router 进入,就能找到开发文档,
    这里可以提供下,链接:https://reacttraining.com/react-router/

    现在路由都是使用 react-router-dom 了。

    二、路由容器

    这个和以前 3.0 版本的路由配置不一样了,现在路由对应两种模式提供两个路由容器。

    • hashhistory
    import { HashRouter as Router } from "react-router-dom";
    
    • browerhistory
    import { BrowserRouter as Router } from "react-router-dom";
    

    Vue 就一个路由容器 <router-view />

    三、如何放置路由

    react-router-dom 书写的路由方式是声明式,可以说是非常的难用,所以一般都是封装成类似 vue-router 路由书写方式。

    <Router>
        <div>
            <Route path="/" render={() => <Child component={App} />} ></Route>
            <Route path="/" component={A} ></Route>
            <Route path="/" children={()=><A/>} ></Route>
            children为函数时不管path匹不匹配都会显示组件,如果不是函数显示效果和component相同
        </div>
    </Router>
    

    路由书写优先级为 component > render > children

    四、路由跳转和传参

    类似 Vue 中的 this.$router,react 路由参数主要包含四部分:

    1. history里面有push
    2. location 有query(search)和params(state)
    location内容
    {
        hash: ""
        pathname: "/about"
        search: ""
        state: {id: 10}
    }
    
    1. match配置路由路径
    2. staticContext

    路由跳转的两种方式:

    • 声明式
    <Link to="/about?user=CondorHero">关于</Link>
    <Link to={{pathname:"/about",search:"CondorHero"}}>关于</Link>
    <Link to={{pathname:"/about",state:{id:10}}}>关于</Link>
    

    比较特殊的还有一个 NavLink 导航链接,不同于 Link ,NavLink 可以增加样式。常用于单页面左侧导航。

    <NavLink to="/about" style={{fontWeight: "bold",color: "red"}}>About</NavLink>
    <NavLink to="/about" activeClassName="className">About</NavLink>
    

    元素处于活动状态时应用于元素的样式, 可以行内也可以类名添加活动样式。

    • 编程式

    push方法,两种配置方式能够 push ,一种是 <Route></Route> 包裹的组件,通过 this.props.history.push

    另一种是通过,history 模块,或者是 useHistory 钩子。

    五、重定向

    新位置将覆盖历史记录堆栈中的当前位置,就像服务器端重定向(HTTP 3xx)一样。

    import { Redirect } from "react-router-dom";
    <Redirect to="/somewhere/else" />
    //用法和Link一样
    

    六、如何在任意组件找到 Vue this 上的路由对象

    Vue 2.0 的路由是绑定在 this 的身上,React 路由只会出现在 和 <Route></Route> 绑定的组件内部,所以其他组件要想跳转路由并传参的话,两种办法。

    • history

    注意⚠️这个 history 不是浏览器原生的。

    import { createBrowserHistory , createHashHistory } from "history";
    
    const customHistory = createBrowserHistory();
    
    console.log(customHistory)
    
    • withRouter
    import { withRouter } from "react-router-dom";
    
    function Main(props){
      console.log(props)
      return (
        <div>
          <h1>你好</h1>
        </div>
      )
    }
    
    const A = withRouter(Main);
    
    /*A仍然作为组件使用*/
    <A></A>
    

    七、路由钩子

    这个路由钩子不是路由守卫,React-router 脑残,在 4.0 把路由拦截给删了,这里出现的路由钩子完全是针对 react-hook而言的路由hooks。react 版本要求大于 16.8。

    1. useHistory
    import { useHistory } from "react-router-dom";
    const history = useHistory();
    history.push({pathname:"/index"})
    
    1. useParams

    useParams返回URL参数的键/值对的对象。使用它来访问match.params当前<Route>,所以只对:

    <Route path="/about/:slug" component={A} ></Route>
    

    组件有效,push 或 params 携带参数都不行。

    1. useLocation

    该useLocation挂钩返回location代表当前URL 的对象。

    重点:配合 useEffect 可作为局部组件守卫使用。

    1. useRouteMatch

    八、回到顶部

    :root{
        scroll-behavior:smooth;
    }
    window.scrollTo(0,0);
    

    九、路由精确匹配问题

    react 路由默认是模糊匹配,例如:

    <Route path="/" render={() => <B />} ></Route>
    <Route path="/index" render={() => <index />} ></Route>
    <Route path="/:user" render={() => <User />} ></Route>
    

    输入 index 三个路径都会匹配。路由添加 exact(精确)属性可以精确匹配。必须是路径和大小写一样。

    还有一个组件是 switch ,组件内部采用模糊匹配,但是只会匹配一个路由。

    <Switch>
        <Route path="/" exact render={() => <B />} ></Route>
        <Route path="/index" render={() => <index />} ></Route>
        <Route path="/:user" render={() => <User />} ></Route>
    </Switch>
    

    十、静态化路由

    相信你也发现了,嵌套路由写起来麻烦维护起来也麻烦。就没有类似 vue-router 那样数组的写法吗。还真没有需要自己来实现。但是官方也维护一个未来版 react-router-config 。不过实在是太简陋了。

    一个简单的用法示例:
    相对 Vue-Router 来讲:

    • 这个routes就相当于children
    • {renderRoutes(this.props.route.routes)} 就相当于 router-view
    
    class B extends React.Component {
        constructor(props) {
            super(props);
            this.route = this.props.route;
        }
        render() {
            return (
                <div>
                    <h1>B</h1>
    
                    {renderRoutes(this.route.routes)}
                </div>
            )
        }
    }
    class Root extends React.Component {
        constructor(props) {
            super(props);
            this.route = this.props.route;
        }
        render() {
            return (
                <div>
                    <h1>我是Root组件</h1>
                    {renderRoutes(this.route.routes)}
                    <h1>我是Root组件</h1>
                </div>
            )
        }
    }
    
    class Index extends React.Component {
        constructor(props) {
            super(props);
            this.route = this.props.route;
        }
        render() {
            return (
                <div>
                    <h2>我是Index组件</h2>
                    {renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
                </div>
            )
        }
    }
    class Child extends React.Component {
        constructor(props) {
            super(props);
        }
        render() {
            return (
                <div>
                    <h3>我是child组件</h3>
                    {renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
                    <h3>我是child组件</h3>
                </div>
            )
        }
    }
    
    
    const routes = [
        {
            component: Root,
            routes: [
                {
                    path: "/",
                    exact: true,
                    component: Index
                },
                {
                    path:"/B",
                    component:B,
                    routes: [
                        {
                            path: "/B/child",
                            component: Child
                        }
                    ]
                }
            ]
        }
    ];
    
    
    
    
    ReactDOM.render(
        <React.StrictMode>
            <Router>
                <div>
                    {renderRoutes(routes)}
                </div>
            </Router>
        </React.StrictMode>,
        document.getElementById('root')
    );
    

    最后

    还有一个知识点:PureComponent 和 Component 的区别?

    PureComponent 只会在 state 和 props 不同才会更新。

    参考:React 的 PureComponent Vs Component

    当前时间 2020年5月5日 星期二 13:22:52

    相关文章

      网友评论

        本文标题:react-router > 4.0 路由

        本文链接:https://www.haomeiwen.com/subject/ybopghtx.html