首先 导航链接应该使用  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. 微服务(Microservices)【翻译】

    微服务 “微服务架构(Microservice Architecture)”一词在过去几年里广泛的传播,它用于描述一种设计应用程序的特别方式,作为一套独立可部署的服务.目前,这种架构方式还没有准确的定 ...

  2. CSS(Cascading Style Sheet)简述

    CSS(Cascading Style Sheet)简述 什么是CSS? css是指层叠样式表 css定义了如何显示HTML元素 css的诞生是为了解决内容与表现分离的问题,可以极大地提高工作效率 样 ...

  3. 16 道嵌入式C语言面试题

    1. 用预处理指令#define 声明一个常数,用以表明 1 年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到 ...

  4. Codeforces 1015F Bracket Substring AC自动机 + dp

    Bracket Substring 这么垃圾的题怎么以前都不会写啊, 现在一眼怎么就会啊.... 考虑dp[ i ][ j ][ k ][ op ] 表示 已经填了 i 个空格, 末尾串匹配到 所给串 ...

  5. ZJOI2019Day2 游记

    原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day2 游记 4-23 乘车. 报到. 自闭. 晚上没睡好. 4-24 上午张哲宇讲课. 幕后点人上去讲题. 然 ...

  6. linux 启动springboot项目

    1.启动 nohup java -jar train-manager.jar --spring.profiles.active=test > out.log & 2.查看进程 ps -e ...

  7. spring-boot-starter-actouator2.1.4与c3p0版本0.9.1.2冲突

    报错前的pom文件: <?xml version="1.0" encoding="UTF-8"?><project xmlns="h ...

  8. 计蒜客 方程的解数 dfs

    题目: https://www.jisuanke.com/course/2291/182237 思路: 来自:https://blog.csdn.net/qq_29980371/article/det ...

  9. C++日志打印

    C++日志打印: %d              十进制有符号整数 %u              十进制无符号整数 %f              浮点数 %s              字符串 % ...

  10. python爬虫实践(一)

    最近在学习爬虫,学完后想实践一下,所以现在准备爬取校花网的一部分图片 第一步,导入需要的库 from urllib import request #用于处理request请求和获得响应 from ur ...