首先 导航链接应该使用  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. Nginx 自定义添加Response Headers 修改server

    之前说过如何隐藏Response Headers中 X-Powered-By 修改php.ini expose_php = Off service php-fpm reload 隐藏Nginx版本号  ...

  2. typora画图

    https://steemit.com/utopian-io/@jubi/typora-typora-tutorial-exquisite-graph https://support.typora.i ...

  3. hdfs api

    经常用到,做个眼 如果是单机版 centos(参照给力星 Hadoop配置),要在  core-site.xml  里面配置   ip:9000  别  localhost:9000 windows ...

  4. unity Tab键实现切换输入框功能

    using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; ...

  5. webserver开发

    https://www.cnblogs.com/zakun/p/5387910.html

  6. VScode加文件头的方式

    在VScode中添加文件头,设置文件编辑者的方式,在软件中查询到file-header插件: 安装好,此时通过是可以生成默认的文件头.如果需要修改配置,在文件=>首选项=>设置中修改: 查 ...

  7. 数组遍历for forEach for..in for..of

    最开始接触的遍历for 通过下标获取数组每一项的值 ,,]; ;i<num.length;i++) { console.log(num[i]) } /*打印2 5 7*/ forEach遍历数组 ...

  8. 2018-2019-2 网络对抗技术 20162329 Exp5 MSF基础应用

    目录 Exp5 MSF基础应用 一.基础问题回答 二.攻击系统 ms08_067攻击(成功) 三.攻击浏览器 ms11_050_mshtml_cobjectelement(Win7失败) 手机浏览器攻 ...

  9. Kafka详细配置

    转自:http://blog.csdn.net/suifeng3051/article/details/38321043?utm_source=tuicool&utm_medium=refer ...

  10. MyBatis(八)联合查询 级联属性封装结果集

    (1)接口中编写方法 public Emp getEmpandDept(); (2)编写Mapper文件 <resultMap type="com.eu.bean.Emp" ...