Code Monkey home page Code Monkey logo

my-react-router-dom's Introduction

  • react-router-dom
    • BrowserRouter

      • 里面组件是Router
      • 维护这2个context, 一个是RouterContext, 一个是HistoryContext
      • RouterContext: 为Provider组件提供的数据,主要有
        • historyhistory是使用history库调用createHistory生成的;
        • location: 使用history监听location发生变化时记录的,维护的一个state, 传递到Provider, 供Consumer拿到
        • match: 拿到location对象后,根据pathname属性,生成一个这样的对象, 这是默认值
        { path: "/", url: "/", params: {}, isExact: pathname === "/" };
        
      • HistoryContext: 为Provider组件提供的数据,2个
        • value: 就是RouterContexthistory
        • children: 渲染子节点
        <BrowserRouter>
            <div>App</div>
        </BrowserRouter>
    • Link

      • 使用React.forwardRef使得ref穿透,能获取到a标签dom
      • 默认是a标签
      • 使用RouterContext.Consumer获取到上下文
      • 使用React.createElement(Component, props)方式创建
      • Component可以自定义,默认是LinkAnchor组件,里面逻辑包括a标签的点击事件等
      • 点击a标签事件做了什么? history.push('/about')
      • 怎么就渲染对应的About组件呢?看Route组件逻辑
    • Route

      <Route exact path="/about">
          <About />
      </Route>
      
      • 匹配到/, 显示组件Aboutexact代表精准匹配到才行

      • Route是怎么判断是否匹配到路由?

        • path值是/about, 当前路由location信息从Consumer里获取
        • 有个matchPath函数,传入当前locationpathname、匹配的路由/about,即matchPath(location.pathname, this.props)
        • matchPath函数,借助path-to-regexp库来处理url和参数,把要匹配路由/about转换为正则匹配规则,通过调用正则的exec方法校验一下,当前路由pathname值是否符合这个规则。
        • 如果匹配成功,拿到一个match对象,里面有描述匹配相关的属性,比如url, 如果url === pathname, 意味着精准匹配,如果需要exact精准匹配,这里有逻辑判断。
        • 总之获得新的match后,构造新的Providervalue数据,这里使用一个RouterContext.Provider,是专门为当前路由下提供数据服务的
      • 构造新的数据

        ... Consumer
        
        const match = matchPath(location.pathname, this.props)
        const props = { ...context, location, match };
        return (
            <RouterContext.Provider value={props}>
                {...}
            </RouterContext.Provider>
        )
        
        ...Consumer
      • 子组件渲染规则是怎样的?

        • 如果match为null,即未匹配成功
          • 如果childrenReactNode, 不会渲染
          • 如果childrenFunction, 会渲染出来
        // 当前url: /test
        <Route exact path="/about">
            <About /> // 不会渲染
        </Route>
        
        // 当前url: /test
        <Route exact path="/about">
            {
                (props) => {
                    return <About />  // 会渲染出来
                }
            }
        </Route>
        • 如果match是个对象,匹配成功

          • 检查是不是有children, 再看看children是不是函数,总之无论是Func还是ReactNode都会渲染
          • 没有children, 检查有没有传component
            • 有: 渲染React.createElement(component, props)
            • 无: 检查有没有传render函数,如果有,执行render函数
        • 所以优先级是: children => component => render

      • 不使用Switch, 有些组件会出现,可能并不是我们预期的,譬如

        // 当前url是: /about
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/:user">:User</Link>
        
        // 结果,About组件会渲染,而且User组件也会渲染,这是因为设计如此灵活

        Switch的加入, 会去寻找匹配的Route, 如果找到了,就停止寻找; 如果到最后都找不到,就渲染没指定pathRoute或指定*Route,或者匹配Redirect的,保证里面匹配渲染一个

    • Switch

      • children中匹配,匹配到第一个符合的,渲染对应的Route
      • 使用React.Children.forEach遍历children
      • 条件: match == null && React.isValidElement(child), 匹配到及不会再继续匹配
      • 使用React.cloneElement(element, {location, computedMatch: match}), 克隆匹配到的Route,返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果
      • 匹配的方式还是使用matchPath函数

my-react-router-dom's People

Contributors

jieliuriver avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.