手写React Router

栏目: 服务器 · 发布时间: 5年前

内容简介:目前常见的路由分为两种,history是h5新出的api,让我们可以在改变url而不刷新页面,主要的几个api是:

目前常见的路由分为两种, HashRouterBrowserRouter

HashRouter

hash 路由的方式主要是通过改变 hash 值来改变 url ,因为只是改变 hash ,所以并不会触发页面刷新,很适合用在单页应用局部更新, window 提供监听 hashChange 方法来监听hash值的改变去更新我们的单页

window.addEventListener('hashchange', function(e) {
  console.log('hashchange', e)
  // 更新页面
})
复制代码

BrowserRouter

history是h5新出的api,让我们可以在改变url而不刷新页面,主要的几个api是:

  1. History.back() : 返回浏览器会话历史中的上一页,跟浏览器的回退按钮功能相同
  2. History.forward() :指向浏览器会话历史中的下一页,跟浏览器的前进按钮相同。
  3. History.go() : 可以跳转到浏览器会话历史中的指定的某一个记录页。
  4. History.pushState() :pushState可以将给定的数据压入到浏览器会话历史栈中,该方法接收3个参数,对象,title和一串url。pushState后会改变当前页面url,但是不会伴随着刷新。
  5. History.replaceState() :replaceState将当前的会话页面的url替换成指定的数据,replaceState后也会改变当前页面的url,但是也不会刷新页面。 以上只是实现改变 url 不刷新页面,我们还需要监听用户前进后退的变化。 popstate 是history的一个监听事件,可以监听history的变化 好了,基本上就是这个原理

实现

实现部分主要是利用 reactcontext api 来存储路由信息,子组件根据 context 值去渲染,代码是由 hook 实现,不了解的,看之前,学习一下React Hook,下面我们来实现一下 BrowserRouter

BrowserRouter

import React, { useState } from "react";
  
let set; // 保存setUrl,因为监听事件咱们值加入一次,所以放外面
function popstate(e) {
  set(window.location.pathname);
}
// 创建context
export const RouterContext = React.createContext(window.location.pathname);

export default function({ children }) {
  const [url, setUrl] = useState(window.location.pathname);
  set = setUrl;

  window.addEventListener("popstate", popstate);

  const router = {
    history: {
      push: function(url, state, title) {
        window.history.pushState(state, title, url);
        setUrl(url);
      },
      replace: function(url, state, title) {
        window.history.replaceState(state, title, url);
        setUrl(url);
      },
      // 下面也需要嵌入setUrl,暂不处理
      go: window.history.go,
      goBack: window.history.back,
      goForward: window.history.forward,
      length: window.history.length
    },
    url: url
  };

  return (
    <RouterContext.Provider value={router}>{children}</RouterContext.Provider>
  );
}
复制代码

Route

import React, { useContext } from "react";
import { RouterContext } from "./BrowserRouter";

function Route({ component, path }) {
  // 获取context
  const { history, url } = useContext(RouterContext);
  const match = {
    path,
    url
  };
  const Component = component;
  return url === path && <Component history={history} match={match} />;
}

export default Route;
复制代码

Link

import React, { useContext } from "react";
import { RouterContext } from "./BrowserRouter";
import styled from "styled-components";

const A = styled.a`
  text-decoration: none;
  padding: 5px;
`;

function Link({ children, to }) {
  const { history } = useContext(RouterContext);
  const onClick = e => {
    e.preventDefault();
    history.push(to);
  };
  return (
    <A href={to} onClick={onClick}>
      {children}
    </A>
  );
}

export default Link;
复制代码

总结

查看Github源码 其实很简单的一个东西,了解原理很容易实现,看了这篇文章,你也可以试着去实现一下 HashRouter .


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java并发编程实战

Java并发编程实战

Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes、Doug Lea / 童云兰 / 机械工业出版社华章公司 / 2012-2 / 69.00元

本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高并发应用程序的吞吐量,如何识别可并行执行的任务,如何提高单线程子系统的响应性,如何确保并发程序执行预期任务,如何提高并发代码的性......一起来看看 《Java并发编程实战》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具