React 中 Link 和 NavLink 组件 activeClassName、activeStyle 属性不生效的问题
首先 导航链接应该使用 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 属性不生效的问题的更多相关文章
- React 深入系列1:React 中的元素、组件、实例和节点
文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...
- React中的高阶组件,无状态组件,PureComponent
1. 高阶组件 React中的高阶组件是一个函数,不是一个组件. 函数的入参有一个React组件和一些参数,返回值是一个包装后的React组件.相当于将输入的React组件进行了一些增强.React的 ...
- React中的高阶组件
高阶组件(HOC, High-Order Component)是React中用于重组组件逻辑的高级技术,是一种编程模式而不是React的api. 直观来讲,高阶组件是以某一组件作为参数返回一个新组件的 ...
- 理解React中es6方法创建组件的this
首发于:https://mingjiezhang.github.io/(转载请说明此出处). 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的 ...
- react中直接调用子组件的方法(非props方式)
我们都知道在 react中,若要在父组件调用子组件的方法,通常我们会采用在父组件定义一个方法,作为props转给子组件,然后执行该方法,可以获取到子组件传回的参数以得到我们的目的. 显而易见,这个执行 ...
- React中使用Ant Table组件
一.Ant Design of React http://ant.design/docs/react/introduce 二.建立webpack工程 webpack+react demo下载 项目的启 ...
- 在React中写一个Animation组件,为组件进入和离开加上动画/过度
问题 在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结.不如自己封装. 思路 原理 以进入时opacity: 0 --> ...
- 如何在react中实现一个倒计时组件
倒计时组件 import React, { Component } from 'react' import $ from 'jquery' import "../../css/spellTE ...
- 批量清除react中的计时器小组件
在Timers的父组件被卸载时,批量清除各个计时器.
随机推荐
- 前端如何做好seo
一:什么是SEO? 搜索引擎优化(Search Engine Optimization),简称SEO.是按照搜索引擎给出的优化建议,以增强网站核心价值为目标,从网站结构.内容建设方案.用户互动传播等角 ...
- DbHelperSQL 增加事务处理方法(2种)
方法一: 1 public static bool ExecuteSqlByTrans(List<SqlAndPrams> list) { bool success = true; Ope ...
- setOnTouchListener在小米手机中不走ACTION_UP而是走ACTION_CANCEL
单点触控: MotionEvent.ACTION_DOWN:手指 初次接触到屏幕 时触发. MotionEvent.ACTION_MOVE:手指 在屏幕上滑动 时触发,会多次触发. MotionEve ...
- ECMAScript 6 之 let 和 const 命令
1.let基本用法 1.1.声明变量 let声明的变量只在它所在的代码块有效. 1.2.不存在变量提升 var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined: let命令 ...
- [sublime] 利用sublime搭建C/C++编译器
gcc/g++配置 先去下载TDM-GCC安装包,这里附下载地址(可能会有弹出界面,不用管他). 现在c盘中建立文件夹 g++,然后以管理员运行,点击Create傻瓜式安装, 这里要改一下安装路径,保 ...
- huginn website agent对提取结果排序
当配置好huginn的website之后,想给提取的内容排个序,那就用下面这堆代码,因为官网里也这么说的, "events_order": [ [ "{{date_pub ...
- 第三方布局框架Neon初探
github地址:https://github.com/mamaral/Neon 居中 设置 view 在 superview 的中心,调用 anchorInCenter()并设置view大小,相当于 ...
- RSP小组——消消乐
RSP小组--消消乐 团队所有博客总结 1.团队第一周作业 2.团队第二周作业 3.RSP小组--团队冲刺博客一 4.RSP小组--团队冲刺博客二 5.RSP小组--团队冲刺博客三 6.RSP小组-- ...
- centos7安装kubeadm
安装配置docker v1.9.0版本推荐使用docker v1.12, v1.11, v1.13, 17.03也可以使用,再高版本的docker可能无法正常使用. 测试发现17.09无法正常使用,不 ...
- SQLServer表、列备注管理
在开发时,为了方便,在SQL SERVER库内对表名.列名进行备注,但在DB部署客户时,想一次清理上述备注值. 特编写如下 SQL,一次清除上述备注内容: declare @table nvarcha ...