• react-router-dom


    1. BrowserRouter 与 HashRouter最显著的区别是,HashRouter的URL中含#,例如:http://example.com/#/your/page

    2. webpack内置就支持code splitting, 但要使用babel(将JSX编译为JavaScript)时,需安装 @babel/plugin-syntax-dynamic-import插件。

    module.exports = {
        "presets": ["@babel/preset-react"],
        "plugins": ["@babel/plugin-syntax-dynamic-import"]
    }

    使用@loadable/component:

    import loadable from "@loadable/component";
    import Loading from "./Loading.js";
    // 动态加载
    const LoadableLogin = loadable(() => import("./login.js"), {
      fallback: <Loading />   // 加载时显示的组件
    });
    
    //在react-router中使用
    <Route path="/" component={loadableLogin}></Route>

     3. react-router-dom hooks

    要求:React >= 16.8,必须使用function声明,不能使用class extends

    3.1. useHistory

    import React from 'react';
    import { connect } from 'react-redux';
    import { useHistory } from 'react-router-dom';
    
    // 使用function不能用class ... extends
    function UserList (props){
        const history = useHistory();
        const users = props.users.map((user,index) => <li key={index}>{user.name}</li>);
        function handleClick (e) {
            history.push('/clock');
        }
    
        return (
            <div>
                <ul>
                    { users }
                </ul>
                <button onClick={handleClick}>Go Back To Clock!</button>
            </div>
        )
    }
    
    export default connect(state => state)(UserList);

    3.2 useParams 获取<Route> path中的参数。

             <Switch>
                <Route path="/login" >
                  <Login />
                </Route>
                <Route path="/clock">
                    <Clock />
                </Route>
                <Route path="/blog/:num" component={BlogPost} />
                <Route path="/">
                    <UserList />
                </Route>
              </Switch>

    注意如果不使用exact, path="/"必须放在最后(按照第一个匹配到的去渲染)

    import React from 'react';
    import {useParams} from 'react-router-dom';
    
    export default function BlogPost(props) {
        let {num} = useParams();
       let {name} = useParams();
    // let name = props.match.params.name; // console.log('in blog', name); return (<div>The params is {name}--{num}</div>); }

    4.1 <BrowserRouter>使用HTML5history API(pushStatereplaceState, popState)

    <BrowserRouter
      basename={optionalString}  // 适用于从子目录中获取资源,指定子目录
      forceRefresh={optionalBool}
      getUserConfirmation={optionalFunc}
      keyLength={optionalNumber}  // location.key的长度,默认6
    >
      <App />
    </BrowserRouter>         

    4.2 <HashRouter> URL中含有#

    <HashRouter
      basename={optionalString}
      getUserConfirmation={optionalFunc}
      hashType={optionalString}  // 用于定义window.location.hash的编码类型
    >
      <App />
    </HashRouter>

    hashType:

    • "slash"- Creates hashes like#/and#/sunshine/lollipops
    • "noslash"- Creates hashes like#and#sunshine/lollipops
    • "hashbang"- Creates“ajax crawlable”(deprecated by Google) hashes like#!/and#!/sunshine/lollipops

    4.3  <MemoryRouter> 用于测试或非浏览器环境(如React Native),可将历史URL记录保存在内存中。

    <MemoryRouter
      initialEntries={optionalArray}  //full-blown location objects with {pathname, search, hassh, state} or string URLS.
      initialIndex={optionalNumber}
      getUserConfirmation={optionalFunc}
      keyLength={optionalNumber}
    >
      <App />
    </MemoryRouter>

    4.4 <Link>

    <Link to="/courses?sort=name" />  // to为String类型,包含pathname, search, hash部分
    <Link
      to={{               // to为Object类型
        pathname: "/courses",
        search: "?sort=name",
        hash: "#the-hash",
        state: { fromDashboard: true }
      }}
    />
    <Link to={location => `${location.pathname}?sort=name`} />  // to为Func类型
    <Link to="/courses" replace />  // replace:点击后将替换history栈中的元素,而不是在栈顶新增

    4.5 <NavLink>与<Link>相同, 在页面中都会以<a></a>的形式渲染出来。

    <NavLink to="/react" activeClassName="hurray">
      React
    </NavLink>
    <NavLink
      to="/faq"
      activeStyle={{
        fontWeight: "bold",
        color: "red"
      }}
    >
      FAQs
    </NavLink>
    <NavLink exact to="/profile">  // exact只有当前选中的标签会显示active样式
      Profile
    </NavLink>
    <NavLink strict to="/events/">  //严格匹配路径右侧的/
      Events
    </NavLink>

    此外,还有aria-current属性,其值可以是:

    • "page" - used to indicate a link within a set of pagination links
    • "step" - used to indicate a link within a step indicator for a step-based process
    • "location" - used to indicate the image that is visually highlighted as the current component of a flow chart
    • "date" - used to indicate the current date within a calendar
    • "time" - used to indicate the current time within a timetable
    • "true" - used to indicate if the NavLink is active

    默认是page.

    4.6 <Prompt> 当用户离开(而开发者此时不希望用户离开此页)时,弹出提示

    <Prompt
      when={formIsHalfFilledOut}
      message="Are you sure you want to leave?"
    />

    4.7 <Redirect>重定向

    <Route exact path="/">
      {loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}
    </Route>

    默认情况下,to参数会取代from参数在history栈中的位置,但如果有push,则会向history栈中新增。

    <Redirect push to="/somewhere/else" />
    // 含匹配模式的redirect
    <Switch>
      <Redirect from='/users/:id' to='/users/profile/:id'/>
      <Route path='/users/profile/:id'>
        <Profile />
      </Route>
    </Switch>

     4.8 <Route>

    (1)
    <
    Route> <NewsReport /> </Route>
    (2)内联component
    <
    Route component={NewsReport}></Route> // 这种方式下,每次render都会重加载(remount)子元素(先unmount旧的,再mount新的)

    相比于方式(2),更推荐使用(3)(4)。在更新时减小render成本。

    (3) render函数
    <Router> <Route path="/home" render={() => <div>Home</div>} /> </Router>
    function FadingRoute({ component: Component, ...rest }) {
      return (
        <Route
          {...rest}
          render={routeProps => (
            <FadeIn>
              <Component {...routeProps} />
            </FadeIn>
          )}
        />
      );
    }
    
    ReactDOM.render(
      <Router>
        <FadingRoute path="/cool" component={Something} />
      </Router>,
      node
    );

    <Route component>优先于<Route render>, 因此不要在同一个<Route>中同时使用。

    (4) <Route children>与<Route render>不同的一点是,无论path是否匹配其函数都会被调用,只不过当URL不匹配时,route的match属性为null.

    (4)
    function ListItemLink({ to, ...rest }) {
      return (
        <Route
          path={to}
          children={({ match }) => (
            <li className={match ? "active" : ""}>
              <Link to={to} {...rest} />
            </li>
          )}
        />
      );
    }
    
    ReactDOM.render(
      <Router>
        <ul>
          <ListItemLink to="/somewhere" />
          <ListItemLink to="/somewhere-else" />
        </ul>
      </Router>,
      node
    );
    <Route
      children={({ match, ...rest }) => (
        {/* Animate will always render, so you can use lifecycles
            to animate its child in and out */}
        <Animate>
          {match && <Something {...rest}/>}
        </Animate>
      )}
    />

    优先级: 1.<Route children> 2.<Route component> 3.<Route render>, 因此同一个<Route>中最多使用其中一个。

    path属性可以是String类型,还可以是Array类型。

    <Route path="/users/:id">
      <User />
    </Route>
    <Route path={["/users/:id", "/profile/:id"]}>
      <User />
    </Route>

    exact属性:是否完全匹配

    pathlocation.pathnameexactmatches?
    /one /one/two true no
    /one /one/two false yes

     strict属性:匹配location.path中是否以 / 结束,对于其后的分段无影响。

    pathlocation.pathnamematches?
    /one/ /one no
    /one/ /one/ yes
    /one/ /one/two yes
    同时含有exact和strict属性。
    pathlocation.pathnamematches?
    /one /one yes
    /one /one/ no
    /one /one/two no
    sensitive属性: 大小写敏感。

    4.9 <Switch>的children只能是<Route>和<Redirect>,并且在匹配时,只有一个匹配到的会被渲染出来。
    <Route>通过path属性进行匹配,而<Redirect>通过from属性进行匹配。如果<Route>不含path属性或者<Redirect>不含from属性,那么总是会匹配当前的路径。
    let routes = (
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
    
        <Route path="/users">
          <Users />
        </Route>
        <Redirect from="/accounts" to="/users" />
    
        <Route>
          <NoMatch />
        </Route>
      </Switch>
    );

    5. history 对象,有以下属性:

    • length - (number) The number of entries in the history stack
    • action - (string) The current action (PUSHREPLACE, or POP)
    • location - (object) The current location. May have the following properties:
      • pathname - (string) The path of the URL
      • search - (string) The URL query string
      • hash - (string) The URL hash fragment
      • state - (object) location-specific state that was provided to e.g. push(path, state) when this location was pushed onto the stack. Only available in browser and memory history.
    • push(path, [state]) - (function) Pushes a new entry onto the history stack
    • replace(path, [state]) - (function) Replaces the current entry on the history stack
    • go(n) - (function) Moves the pointer in the history stack by n entries
    • goBack() - (function) Equivalent to go(-1)
    • goForward() - (function) Equivalent to go(1)
    • block(prompt) - (function) 阻塞导航

    history对象是易变的,所以一般要获取location对象时不通过history对象,而是通过<Route>的渲染属性。

    class Comp extends React.Component {
      componentDidUpdate(prevProps) {
        // will be true
        const locationChanged =
          this.props.location !== prevProps.location;
    
        // INCORRECT, will *always* be false because history is mutable.
        const locationChanged =
          this.props.history.location !== prevProps.history.location;
      }
    }
    
    <Route component={Comp} />;

    6. location对象

    {
      key: 'ac3df4', // not with HashHistory!
      pathname: '/somewhere',
      search: '?some=search-string',
      hash: '#howdy',
      state: {
        [userDefined]: true
      }
    }

    获取location对象的方式:

    以上方式获取的location对象可以用于生命周期hooks中。不要通过history.location(易变的)获取。

    componentWillReceiveProps(nextProps) {
      if (nextProps.location !== this.props.location) {
        // navigated!
      }
    }

    location对象可用于以下:

    const location = {
      pathname: '/somewhere',
      state: { fromDashboard: true }
    }
    
    <Link to={location}/>
    <Redirect to={location}/>
    history.push(location)
    history.replace(location)

    此外,可以将location对象用在以下场景中,

    强制使用给定的location对象,而不是router默认的location.

    7. match对象:<Route>如何进行匹配的。包含以下属性:

    • params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path
    • isExact - (boolean) true if the entire URL was matched (no trailing characters)
    • path - (string) The path pattern used to match. Useful for building nested <Route>s
    • url - (string) The matched portion of the URL. Useful for building nested <Link>s

    match对象可用于以下场景:

    null match 当<Route>的path属性与当前的location不匹配时,其children属性对应的函数仍然会被调用,只不过此时match对象为null

    // location.pathname = '/matches'
    <Route path="/does-not-match"
      children={({ match }) => (
        // match === null
        <Route
          render={({ match: pathlessMatch }) => (
            // pathlessMatch === ???
          )}
        />
      )}
    />

    没有path属性的<Route>,其match对象继承自父级<Route>。如果父级<Route>的match为null,那么子<Route>的match也为null.对于无path属性,且父级<Route> match为null的子<Route>,通过调用其children属性进行渲染。

    8. withRouter 高阶组件: withRouter可以包装任何自定义组件,将react-router 的 history,location,match 三个对象传入。
    无需一级级传递react-router 的属性,当需要用的router 属性的时候,在组件外包上withRouter(),就可以拿到需要的路由信息。

    import React from "react";
    import PropTypes from "prop-types";
    import { withRouter } from "react-router";
    
    // A simple component that shows the pathname of the current location
    class ShowTheLocation extends React.Component {
      static propTypes = {
        match: PropTypes.object.isRequired,
        location: PropTypes.object.isRequired,
        history: PropTypes.object.isRequired
      };
    
      render() {
        const { match, location, history } = this.props;
    
        return <div>You are now at {location.pathname}</div>;
      }
    }
    
    // Create a new component that is "connected" (to borrow redux
    // terminology) to the router.
    const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

    WrappedComponent用于测试组件是否孤立于其他组件。

    // MyComponent.js
    export default withRouter(MyComponent)
    
    // MyComponent.test.js
    import MyComponent from './MyComponent'
    render(<MyComponent.WrappedComponent location={{...}} ... />)
  • 相关阅读:
    [转]三五个人十来条枪 如何走出软件作坊成为开发正规军
    [转]asp.net页面字体变大问题总结
    [练手7]传值和传引用区别
    [练手3]选择排序
    [练手5]希尔排序
    oracle用select for update 中断后无法操作表的处理:杀掉SESSION
    [转]最省时管理法:让你一天随意
    [练手4]插入排序
    没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问权限
    NUnit单元测试编写指南
  • 原文地址:https://www.cnblogs.com/ceceliahappycoding/p/12416068.html
Copyright © 2020-2023  润新知