zoukankan      html  css  js  c++  java
  • 四、React全家桶(二)

    react-router

    react-router包含3个库,react-router、react-router-dom和react-router-native。react-router提供最基本的路由功能,实际使用的时候我们不会直接安装react-router,而是根据应用运行的环境选择安装react-router-dom(在浏览器中使用)或react-router-native(在rn中使用)。react-router-dom和react-router-native都依赖react-router,所以在安装时,react-router也会自动安装,创建web应用

    安装:

    npm install react-router-dom --save

    基本使用:

    react-router中奉行一切皆组件的思想,路由器-Router、链接-Link、路由-Route、独占-Switch、重定向-Redirect 都以组件形式存在

    Route渲染优先级:children > component > render

    创建RouterPage.js

    import React, {Component} from 'react'
    import {BrowserRouter, Link, Route} from 'react-router-dom';
    import HomePage from './HomePage';
    import UserPage from './UserPage';
    
    export default class RouterPage extends Component {
      render() {
        return (
          <div>
            <h1>RouterPage</h1>
            <BrowserRouter>
              <nav>
                <Link to='/'>首页</Link>
                <Link to='/user'>用户中心</Link>
              </nav>
              {/* 跟路由需要添加 exact ,实现精确匹配 */}
              <Route exact path='/' component={HomePage}/>
              <Route path='/user' component={UserPage}/>
            </BrowserRouter>
          </div>
        )
      }
    }

    404页面---独占路由 Switch

    设定一个没有path的路由在路由列表最后面,表示一定匹配

    <BrowserRouter>
      <nav>
        <Link to='/'>首页</Link>
        <Link to='/user'>用户中心</Link>
      </nav>
      {/* 添加Switch表示仅匹配一个 */}
      <Switch>
      {/* 跟路由需要添加 exact ,实现精确匹配 */}
        <Route exact path='/' component={HomePage}/>
        <Route path='/user' component={UserPage}/>
        <Route component={()=><div>404</div>}/>
      </Switch>
    </BrowserRouter>

    动态路由

    使用 :id 的形式定义动态路由

    定义路由:

    <Route path='/search/:id' component={Search}/>

    添加导航链接:

    <Link to={'/search/' + searchId}>搜索</Link>

    创建Search并获取参数:

    import React, {Component} from 'react'
    import {BrowserRouter, Link, Route, Switch} from 'react-router-dom';
    
    function Search(props){
      const {id} = props.match.params
      return <div>
        <h1>Search:{id}</h1>
      </div>
    }
    
    export default class RouterPage extends Component {
      render() {
        const searchId = 123
        return (
          <div>
            <h1>RouterPage</h1>
            <BrowserRouter>
              <nav>
                <Link to={'/search/' + searchId}>搜索</Link>
              </nav>
              <Switch>
                <Route path='/search/:id' component={Search}/>
              </Switch>
            </BrowserRouter>
          </div>
        )
      }
    }

    路由嵌套

    Route组件嵌套在其他页面组件中就产生了嵌套关系

    修改Search,添加新增和详情

    function Search(props){
      const {id} = props.match.params
      return <div>
        <h1>Search:{id}</h1>
        <nav>
          <Link to="/search/add">新增</Link>
          <Link to={"/search/detail/" + id}>详情</Link>
        </nav>
        <Route path='/search/add' component={()=><div>add</div>}/>
        <Route path={"/search/detail/:" + id} component={Detail}/>
      </div>
    }
    
    function Detail(){
      return <div>
        <h1>Detail</h1>
      </div>
    }

    路由守卫

    思路:创建高阶组件包装Route使其具有权限判断功能 

    对 UserPage 做路由守卫,在RouterPage.js 中

    <PrivateRoute path='/user' component={UserPage}/>
    <Route path='/login' component={LoginPage}/>

    PrivateRoute.js

    import React, { Component } from 'react'
    import {Route, Redirect} from 'react-router-dom';
    import UserPage from './UserPage';
    
    export default class PrivateRoute extends Component {
      render() {
        const {isLogin = false, location} = this.props
        const redirect = location.pathname
        console.log(this.props);
        return isLogin ? (
          <Route path='/user' component={UserPage}/>
        ) : (
          <Redirect to="/login"/>
        )
      }
    }

    与HashRouter对比:

    1、HashRouter最简单,不需要服务器渲染,靠浏览器的#来区分path就可以,BrowserRouter需要服务器端对不同的URL返回不同的HTML

    后端配置可参考  https://react-guide.github.io/react-router-cn/docs/guides/basics/Histories.html

    2、BrowserRouter使用HTML5历史API(pushState,replaceState 和 propstate 事件),让页面的UI同步与URL

    3、HashRouter 不支持 location.key 和location.state,动态路由跳转需要通过?传递参数

    4、Hash不需要服务器任何配置就可以运行,如果你刚刚入门,那就使用它吧。但是我们不推荐在实际线上环境中用到它,因为每一个web应用都应该渴望使用 browserHistory

    实现BrowserRouter

    历史管理对象history初始化及向下传递,location变更监听

    MyRouterPage.js

    import React, { Component } from 'react'
    // import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
    import { BrowserRouter, Link, Route } from '../kReact-router-dom';
    import HomePage from './HomePage';
    import UserPage from './UserPage';
    
    export default class MyRouterPage extends Component {
      render() {
        return (
          <div>
            <h1>MyRouterPage</h1>
            <BrowserRouter>
              <nav>
                <Link to="/">首页</Link>
                <Link to="/user">用户中心</Link>
              </nav>
                <Route exact path="/" component={HomePage}/>
                <Route path="/user" component={UserPage}/>
            </BrowserRouter>
          </div>
        )
      }
    }

    kReact-router-dom.js

    import React, { Component, useContext } from 'react'
    import { createBrowserHistory } from 'history';
    
    const RouterContext = React.createContext()
    const RouterProvider = RouterContext.Provider
    const RouterConsumer = RouterContext.Consumer
    
    export class BrowserRouter extends Component {
      constructor(props) {
        super(props)
        this.history = createBrowserHistory()
        this.state = {
          location: this.history.location
        }
        this.unlisten = this.history.listen(location => {
          this.setState({ location })
        })
        console.log(this.history);
      }
      componentWillUnmount() {
        if (this.unlisten) {
          this.unlisten()
        }
      }
      render() {
        const { children } = this.props
        return <RouterProvider value={{ history: this.history, location: this.state.location }}>
          {children}
        </RouterProvider>
      }
    }
    
    export function Route(props) {
      const ctx = useContext(RouterContext)
      const { location } = ctx
      const { path, component } = props
      const matchCurrent = path === location.pathname
      return matchCurrent ? React.createElement(component) : null
    }
    
    export class Link extends Component {
      handlerClick = (event, history) => {
        const { to } = this.props
        event.preventDefault()
        history.push(to)
      }
      render() {
        const { children, to } = this.props
        return <RouterConsumer>
          {
            ctx => <a href={to} onClick={event => this.handlerClick(event, ctx.history)}>
              {children}
            </a>
          }
        </RouterConsumer>
      }
    }
  • 相关阅读:
    LeetCode
    lintcode--剑指offer
    lintcode--剑指offer---41--50道
    LeetCode中的bug!!!!!!
    常用知识点
    lintcode--剑指offer---31--40道
    LeetCode--链表
    Java设计实践课练习题
    lintcode--剑指offer---21--30道
    Java设计实践课的LeetCode题目
  • 原文地址:https://www.cnblogs.com/haishen/p/11704139.html
Copyright © 2011-2022 走看看