react-router原理之Link跳转

react-router原理之路径匹配一文中讲了react-router如何根据url进行路径匹配进而完成不同的组件渲染。接下来继续讲一下如何改变url。仍旧以官网为例,演示地址

const BasicExample = () => (
  
    
  • "/">Home
  • "/about">About
  • "/topics">Topics
... "/" component={Home} /> "/about" component={About} /> "/topics" component={Topics} />
); 复制代码

可以看出Link的作用就是接受点击然后触发url地址的变更,Link组件最终在浏览器中是以何种方式存在的呢?通过查看页面的Element可以看到Link最终会转成标签,上面的例子中的Link在浏览器中的样子是这样的


复制代码

既然最终Link被转换成上面标签的形式,那么和代码里直接写a标签有什么区别呢?

最大的区别表象体现在是否有主文档请求,标签一定会出现,而Link则是通常不出现(除非特殊的配置)

Link不只是标签

Link在最后渲染的时候其实是创建了标签,同时添加了一个onClick的监听事件,onClick事件处理函数中做了两件事:

render() {
    ....
    return (
      
    );
  }
  
  handleClick = event => {
    if (this.props.onClick) this.props.onClick(event);

    if (
      !event.defaultPrevented && // onClick prevented default
      event.button === 0 && // ignore everything but left clicks
      !this.props.target && // let browser handle "target=_blank" etc.
      !isModifiedEvent(event) // ignore clicks with modifier keys
    ) {
      event.preventDefault();

      const { history } = this.context.router;
      const { replace, to } = this.props;

      if (replace) {
        history.replace(to);
      } else {
        history.push(to);
      }
    }
  };
复制代码

Link什么情况下阻止默认行为

同时下列四个条件时就会阻止默认行为

  • Link的onClick回调中不包含event.preventDefault()代码
  • 点击按键是左键
  • Link的props未定义target
  • 点击操作触发时没有功能键(ctrl、shift等)被按下
!event.defaultPrevented &&  event.button === 0 && !this.props.target && !isModifiedEvent(event)
复制代码

特殊的Link

react-router中除了Link还有一个NavLink,NavLink是一种特殊的Link,它的特殊体现在当与url匹配时生成的标签上会带有一些样式信息(通过activeClassName和activeStyle定义样式)。

"/faq"
  activeClassName="selected"
>FAQs

"/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs
复制代码

NavLink的特性需要做url的匹配查询,之前在讲路径匹配的时候讲到Route就是负责用来匹配路径渲染组件的,因此这里正适合引入Route来做匹配。匹配成功渲染带样式的Link,匹配失败则渲染不带样式的Link。

Route定义路径关联组件的方式有三种:

  • render
  • component
  • children

render与component方式定义的组件当不匹配时是不会渲染组件的

children方式则只是将匹配规则传入进来,具体是否渲染由children自己定义。children的这个特性刚好符合满足NavLink的要求。

明白了NavLink的大体思路后可以去看看源码的具体实现。

NavLink具体实现

render() {
  return (
     {
        const isActive = !!(getIsActive ? getIsActive(match, location) : match);

        return (
           i).join(" ")
                : className
            }
            style={isActive ? { ...style, ...activeStyle } : style}
            aria-current={(isActive && ariaCurrent) || null}
            {...rest}
          />
        );
      }}
    />
  );
}
复制代码

进入下一篇react-router原理之幕后history

你可能感兴趣的:(react-router原理之Link跳转)