首先 导航链接应该使用  NavLink 而不再是  Link

NavLink 使用方法见 https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/NavLink.md

NavLink 和  PureComponent 一起使用的时候,会出现 激活链接样式(当前页面对应链接样式,通过 activeClassName、activeStyle 设置) 不生效的情况。效果如下:

刷新页面后导航激活样式生效,点击导航链接的时候 url 跳转,但是导航激活样式不生效。

上图效果对应代码:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>NavLink And PureComponent</title>
  6.  
  7. <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
  8. <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  9. <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
  10. <script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
  11.  
  12. <style>
  13. .menu-link {
  14. display: inline-block;
  15. width: 100px;
  16. text-decoration: none;
  17. text-align: center;
  18. background: #dedede;
  19. }
  20. .menu-link.active {
  21. background: tomato;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <div id="app"></div>
  27. <script type="text/babel">
  28. // import ReactRouterDOM, { HashRouter, Route } from 'react-router-dom';
  29. // import React, { Component, PureComponent } from 'react';
  30.  
  31. const { HashRouter, Route, NavLink } = ReactRouterDOM;
  32. const { Component, PureComponent } = React;
  33.  
  34. class Menu extends PureComponent {
  35. render() {
  36. return (
  37. <div>
  38. <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/home'>首页</NavLink>
  39. <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/help'>帮助页</NavLink>
  40. </div>
  41. );
  42. }
  43. }
  44.  
  45. class App extends PureComponent {
  46. render() {
  47. return (
  48. <HashRouter>
  49. <div>
  50. <Menu />
  51. <Route path='/home' component={ () => <div>首页内容</div> } />
  52. <Route path='/help' component={ () => <div>帮助页内容</div> } />
  53. </div>
  54. </HashRouter>
  55. );
  56. }
  57. }
  58.  
  59. ReactDOM.render(
  60. <App />,
  61. document.getElementById('app')
  62. );
  63. </script>
  64. </body>
  65. </html>

为什么不生效,我们在使用  PureComponent  之前应该知道 它相当于对组件的  props  和  state 进行浅比较,如果相等则不更新,以此来进行优化,防止多余更新。

而在上面的例子中 就相当于

  1. class Menu extends Component {
  2. shouldComponentUpdate(props, state) {
  3. console.log(props, this.props, props === this.props); // {} {} true
  4. console.log(state, this.state, state === this.state); // null null true
  5. // 由于 props 和 state 都不发生变化 下面的表达式会返回 false 组件不会发生更新
  6. return !shallowEqual(props, this.props) || !shallowEqual(state, this.state);
  7. }
  8.  
  9. render() {
  10. return (
  11. <div>
  12. <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/home'>首页</NavLink>
  13. <NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/help'>帮助页</NavLink>
  14. </div>
  15. );
  16. }
  17. }

其中浅比较函数 shallowEqual 的实现(https://blog.csdn.net/juzipidemimi/article/details/80892440)

  1. function is(x, y) {
  2. // SameValue algorithm
  3. if (x === y) {
  4. // Steps 1-5, 7-10
  5. // Steps 6.b-6.e: +0 != -0
  6. // Added the nonzero y check to make Flow happy, but it is redundant,排除 +0 === -0的情况
  7. return x !== 0 || y !== 0 || 1 / x === 1 / y;
  8. } else {
  9. // Step 6.a: NaN == NaN,x和y都不是NaN
  10. return x !== x && y !== y;
  11. }
  12. }
  13.  
  14. function shallowEqual(objA, objB) {
  15. if (is(objA, objB)) {
  16. return true;
  17. }
  18.  
  19. if (
  20. typeof objA !== 'object' ||
  21. objA === null ||
  22. typeof objB !== 'object' ||
  23. objB === null
  24. ) {
  25. return false;
  26. }
  27.  
  28. const keysA = Object.keys(objA);
  29. const keysB = Object.keys(objB);
  30.  
  31. if (keysA.length !== keysB.length) {
  32. return false;
  33. }
  34.  
  35. // Test for A's keys different from B.
  36. for (let i = 0; i < keysA.length; i++) {
  37. if (
  38. !hasOwnProperty.call(objB, keysA[i]) ||
  39. !is(objA[keysA[i]], objB[keysA[i]])
  40. ) {
  41. return false;
  42. }
  43. }
  44.  
  45. return true;
  46. }

所以组件  Menu 不会发生更新,所以其子组件  NavLink 自然也就不会被更新。

那么该如果解决这个问题呢?

最简单的当然就是使用  Component  替换  PureComponent

如果不想更改 PureComponent 的话,可以通过给组件传入当前  location 作为属性来解决。

NavLink 是通过监听当前所在 location 来更新链接样式的,所以如果能在 location 改变的时候,更新组件就可以了,而做到这一点,只需要把  location 作为一个属性传入组件。

最简单的办法,把导航组件也作为一个 Route,并且能动态匹配所有路径,这样  location 会自动作为属性被注入到组件。

  1. class App extends PureComponent {
  2. render() {
  3. return (
  4. <HashRouter>
  5. <div>
  6. <Route path="/:place" component={Menu} />
  7. <Route path='/home' component={ () => <div>首页内容</div> } />
  8. <Route path='/help' component={ () => <div>帮助页内容</div> } />
  9. </div>
  10. </HashRouter>
  11. );
  12. }
  13. }

全文参考: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

如果能帮助到你,点个赞呗

React 中 Link 和 NavLink 组件 activeClassName、activeStyle 属性不生效的问题的更多相关文章

  1. React 深入系列1:React 中的元素、组件、实例和节点

    文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...

  2. React中的高阶组件,无状态组件,PureComponent

    1. 高阶组件 React中的高阶组件是一个函数,不是一个组件. 函数的入参有一个React组件和一些参数,返回值是一个包装后的React组件.相当于将输入的React组件进行了一些增强.React的 ...

  3. React中的高阶组件

    高阶组件(HOC, High-Order Component)是React中用于重组组件逻辑的高级技术,是一种编程模式而不是React的api. 直观来讲,高阶组件是以某一组件作为参数返回一个新组件的 ...

  4. 理解React中es6方法创建组件的this

    首发于:https://mingjiezhang.github.io/(转载请说明此出处). 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的 ...

  5. react中直接调用子组件的方法(非props方式)

    我们都知道在 react中,若要在父组件调用子组件的方法,通常我们会采用在父组件定义一个方法,作为props转给子组件,然后执行该方法,可以获取到子组件传回的参数以得到我们的目的. 显而易见,这个执行 ...

  6. React中使用Ant Table组件

    一.Ant Design of React http://ant.design/docs/react/introduce 二.建立webpack工程 webpack+react demo下载 项目的启 ...

  7. 在React中写一个Animation组件,为组件进入和离开加上动画/过度

    问题 在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结.不如自己封装. 思路 原理 以进入时opacity: 0 --> ...

  8. 如何在react中实现一个倒计时组件

    倒计时组件 import React, { Component } from 'react' import $ from 'jquery' import "../../css/spellTE ...

  9. 批量清除react中的计时器小组件

    在Timers的父组件被卸载时,批量清除各个计时器.

随机推荐

  1. Go的安装

    0.  环境:Ubuntu16.04 64位 1.  下载安装包,地址:https://golang.org/dl,以1.8版本为例,下载go1.8.linux-amd64.tar.gz 2.  解压 ...

  2. LOJ#3043.【ZJOI2019】 线段树 线段树,概率期望

    原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day1T2.html 前言 在LOJ交了一下我的代码,发现它比选手机快将近 4 倍. 题解 对于线段树上每一个节 ...

  3. 使用Kazoo操作ZooKeeper服务治理

    单机服务的可靠性及可扩展性有限,某台服务宕机可能会影响整个系统的正常使用:分布式服务能够有效地解决这一问题,但同时分布式服务也会带来一些新的问题,如:服务发现(新增或者删除了服务如何确保能让客户端知道 ...

  4. vue小白必看的生命钩子函数图解

    还有3个钩子并未出现在图上: 1.activated生命周期钩子函数在keep-alive 组件激活时调用,该钩子在服务器端渲染期间不被调用. 2.deactivated生命周期钩子函数在keep-a ...

  5. C# 0xC0000005 捕获

    [HandleProcessCorruptedStateExceptions]//捕获c++异常 [SecurityCritical]//捕获c++异常 public void xxx() { try ...

  6. 洛谷.5300.[GXOI/GZOI2019]与或和(单调栈)

    LOJ BZOJ 洛谷 想了一个奇葩的单调栈,算的时候要在中间取\(\min\),感觉不靠谱不写了=-= 调了十分钟发现输出没取模=v= BZOJ好逗逼啊 题面连pdf都不挂了 哈哈哈哈 枚举每一位. ...

  7. Oracle导入数据无法导出空表的问题

    Oracle 11G在用export导出时,空表不能导出,11G R2中有个新特性,当表无数据时,不分配segment,以节省空间. 那么我们应该如何导出空表: 利用如下语句生成alter语句,未每个 ...

  8. selenium 不同版本Driver

    selenium进行UI自动化测试需要Driver支持,不同的浏览器需要不同的Driver,之前使用的Driver可以正常运行,但是总会报一些莫名的问题,经过查找,原来IE的Driver需要与sele ...

  9. docker用法记录

    下载docker镜像 docker pull ubuntu 查看所有docker镜像 docker images 运行docker镜像且进入shell docker run -it ubuntu ba ...

  10. node02

    1.使用已有的知识实现一个简单的登录和注册的界面 请求有请求接口有请求页面的,我们需要加以区分 以下是客户端代码 <!DOCTYPE html> <html lang="e ...