美文网首页react
简易手写react-router(函数式组件)

简易手写react-router(函数式组件)

作者: 你的时间非常值钱 | 来源:发表于2020-03-13 16:26 被阅读0次

自己实现一个react-router

期望最简单的使用效果

export default () => {
      return (
        <>
            <Link to="/a">菜单a</>
            <Link to="/b">菜单b</>
        </>
        <Router>
            <Route path="/a"><A /></Route>
            <Route path="/b"><B /></Route>
        </Router>
      )
}
Router一般分HashRouter和BrowserHistoryRouter,原理区别分别是对location.hash和history api的处理

先写一些公用组件
// Link
const Link = ({ children }) => <a>children</a>

// Route 
const Route = () => {}

实现HashRouter

原理是在Link上绑定点击更改hash值事件,利用浏览器监听hash值的变化做相应的动作(渲染相应组件),因为是函数组件,会用到useEffect,useState

// HashRouter
const HashRouter = ({ children }) => {
  const [hash, setHash] = useState(window.location.hash)
  // hash变更触发
  const hashChange = e => {
      const { newURL } = e
      setHash(newURL.slice(newURL.indexOf('#')))
  }
  // 记得销毁时要清除绑定
  useEffect(() => {
    window.addEventListener('hashchange', hashChange)
    return window.removeEventListener('hashchange', hashChange)
  }, [])
 // 为什么不用children遍历,因为children有3种情况(1. 没子组件会返回undefined 2.单个子组件返回一个对象 3.多个子组件返回数组),而React.Children会自行判断,比较安全,当然要多个null兜底,因为返回undefined也会报错
  return React.Children.map(children, child => {
      if(child.type.name === 'Route') {
        if(child.props.path === hash) {
            return child.props.children
        }
        return null
      }
      return child.props.children
  }) || null
}

相应Link也要添加点击逻辑

const Link = ({ to, children, handleClick }) => {
    const handleClick = () => window.location.hash = to
    <span onClick={handleClick}>{children}</span>
}
加一点排版

最简单的功能就这样完成了

...
<div id='menu'>
    <div><Link to='a'>a组件</Link></div<
</div>
<div id='container'>
    <HashRouter>
       <Route path='/a'><A /></Route>
    </HashRouter>
</div>

接着搞嵌套路由看看

export default () => <div style={containerStyle}>
  <div style={menuStyle}>
    <div><Link to='#/a'>a组件</Link></div>
    <div><Link to='#/b'>b组件</Link></div>
    <div><Link to='#/c'>C组件</Link></div>
  </div>
  <div style={contentStyle}>
    <HashRouter>
      <Route path="#/a"><A /></Route>
      <Route path="#/b"><B /></Route>
      <Route path="#/c"><C /></Route>
    </HashRouter>
  </div>

</div>

const C1 = () => <div>我是C1</div>
const C2 = () => <div>我是C2</div>

const C = () => (
  <div>
    <Link to='#/c/c1'>C1组件</Link>
    <Link to='#/c/c2'>C2组件</Link>
    <div style={contentStyle}>
      <h2>c下面的组件</h2>
      <HashRouter>
        <Route path="#/c/c1"><C1 /></Route>
        <Route path="#/c/c2"><C2 /></Route>
      </HashRouter>
    </div>
  </div>
)
#/c的效果 点击C1

点击C1或C2的Link,发现整个C都消失了,分析到因为当前hash应当是#/c/c1,而C组件本身对于要在#/c的时候才会渲染,用全等判断自然不会渲染出来,子组件C1和C2肯定也不会出来


hash全等

将全等改成includes,发现效果出来了

    if (child.type.name === 'Route') {
      if (hash.includes(child.props.path)) {
        return child.props.children
      }
      return null
    }
改动后

待续更新BrowserRouter

相关文章

  • 简易手写react-router(函数式组件)

    自己实现一个react-router 期望最简单的使用效果 Router一般分HashRouter和Browser...

  • react-router v6嵌套路由简单案例

    react-router V6版本路由用法和V5用法差距较大,一个简单的使用案例 新版本组件也开始使用函数式组件+...

  • React 函数式组件

    简单函数式组件 使用 hook 的函数式组件

  • React入门(二)

    组件 1.函数式组件 什么是函数式组件创建一个函数,只要函数中返回一个新的JSX元素,则为函数式组件 调用组件可以...

  • React - 类组件创建

    React创建组件有两种方式 函数式组件 类组件函数式组件已经学过,现在看下类组件怎么写。 函数式组件和类组件区别...

  • React 面向组件编程

    函数式组件// 创建函数式组件function MyComponent() {console.log(this)/...

  • 函数式组件

    函数式组件 函数式组件,即无状态,无法实例化,内部没...

  • Render渲染函数和JSX

    render函数 h( 元素,属性,值 ) 中 h 不能少 使用 list组件中调用 函数式组件 定义函数式组件 ...

  • recompose函数式库 + ( git? ) + ( vo

    (一) recompose 函数式组件,高阶组件库 (1) withState 因为函数式组件中没有state,但...

  • Vue.js 2函数式组件学习

    什么是函数式组件? 函数式组件就是函数是组件,组件是函数,它的特征是没有内部状态、没有生命周期钩子函数、没有thi...

网友评论

    本文标题:简易手写react-router(函数式组件)

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