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

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

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

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

上图效果对应代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NavLink And PureComponent</title> <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script> <style>
.menu-link {
display: inline-block;
width: 100px;
text-decoration: none;
text-align: center;
background: #dedede;
}
.menu-link.active {
background: tomato;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
// import ReactRouterDOM, { HashRouter, Route } from 'react-router-dom';
// import React, { Component, PureComponent } from 'react'; const { HashRouter, Route, NavLink } = ReactRouterDOM;
const { Component, PureComponent } = React; class Menu extends PureComponent {
render() {
return (
<div>
<NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/home'>首页</NavLink>
<NavLink className="menu-link" activeClassName="active" activeStyle={{color: '#fff'}} to='/help'>帮助页</NavLink>
</div>
);
}
} class App extends PureComponent {
render() {
return (
<HashRouter>
<div>
<Menu />
<Route path='/home' component={ () => <div>首页内容</div> } />
<Route path='/help' component={ () => <div>帮助页内容</div> } />
</div>
</HashRouter>
);
}
} ReactDOM.render(
<App />,
document.getElementById('app')
);
</script>
</body>
</html>

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

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

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

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

function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
// Added the nonzero y check to make Flow happy, but it is redundant,排除 +0 === -0的情况
return x !== 0 || y !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN,x和y都不是NaN
return x !== x && y !== y;
}
} function shallowEqual(objA, objB) {
if (is(objA, objB)) {
return true;
} if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false;
} const keysA = Object.keys(objA);
const keysB = Object.keys(objB); if (keysA.length !== keysB.length) {
return false;
} // Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
if (
!hasOwnProperty.call(objB, keysA[i]) ||
!is(objA[keysA[i]], objB[keysA[i]])
) {
return false;
}
} return true;
}

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

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

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

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

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

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

class App extends PureComponent {
render() {
return (
<HashRouter>
<div>
<Route path="/:place" component={Menu} />
<Route path='/home' component={ () => <div>首页内容</div> } />
<Route path='/help' component={ () => <div>帮助页内容</div> } />
</div>
</HashRouter>
);
}
}

全文参考: 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. Flink写入kafka时,只写入kafka的部分Partitioner,无法写所有的Partitioner问题

    1. 写在前面 在利用flink实时计算的时候,往往会从kafka读取数据写入数据到kafka,但会发现当kafka多个Partitioner时,特别在P量级数据为了kafka的性能kafka的节点有 ...

  2. RabbitMQ 使用QOS(服务质量)+Ack机制解决内存崩溃的情况

    当消息有几万条或者几十万条的时候,如果消费的方式不对,会造成内存崩溃的情况 一:consumer 1. 短链接:basicget 独自去获取message... request 的方式去获取,断开式. ...

  3. C# 通过 Quartz .NET 实现Timer Job并将其注册成为Windows Service

    之前的一篇文章讲述了如何通过 Quartz .NET 实现 Timer Job (http://www.cnblogs.com/mingmingruyuedlut/p/8037263.html) 在此 ...

  4. CYJian的新春虐题赛

    题解: t1: 算了一下发现乘法也是可以莫比乌斯反演的 然后就直接对原式莫比乌斯反演了 大概加法是$\mu {(i)}*f(i)$ 乘法就是$f(i)^{\mu {(i)}}$ 然后这个算法成功达到$ ...

  5. 关于Hbase的预分区,解决热点问题

    Hbase默认建表是只有一个分区的,开始的时候所有的数据都会查询这个分区,当这个分区达到一定大小的时候,就会进行做split操作: 因此为了确保regionserver的稳定和高效,应该尽量避免reg ...

  6. Adams 2013自定义插件方法zz

    1.Adams插件介绍 Adams的高级模块(如Controls控制模块.Vibration振动模块.Durability耐久性模块等)是以插件的形式集成在Adams软件中.通过Adams提供的插件管 ...

  7. BZOJ1431 : MLand

    考虑任意一棵生成树,它的代价是一个一次函数. 因此所有生成树的最小值随着时间变化呈现出的是一个上凸壳. 三分查找最大值即可. 时间复杂度$O(m\log m\log w)$. #include< ...

  8. vuex的一些学习

    刚开始学vuex看文档看的一脸懵逼,故而网上各种查找资料,视频去观看学习,虽然看了很多还是很蒙圈,最近看了一个讲vuex的视频还有一个 类似的简书文档从中学到了很多,慢慢理清了头绪,至此记录一下,共同 ...

  9. 2、java基础

    1.注释  -----> 注释不会出现在字节码文件中.即Java编译器编译时会跳过注释语句. // 单行注释 ,注释内容从//到本行末尾 /*  */ 多行注释,/* */ 注释不能嵌套 /** ...

  10. angular.lowercase()

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...