Javascript 如何在 react-router 中为 Link 或 IndexLink 的包装元素设置 activeClassName?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35053161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set activeClassName for wrapper element of Link or IndexLink in react-router?
提问by abekenza
I am new to the ReactJS world, and would like to know how can I pass active class name to the <li>
element instead of <a>(Link)
element.
我是 ReactJS 世界的新手,想知道如何将活动类名传递给<li>
元素而不是<a>(Link)
元素。
Now I have this kind of code. The anchor class changes when clicked.
现在我有这种代码。单击时锚点类会发生变化。
<li><IndexLink to='/' activeclassName='active'>A</IndexLink></li>
<li><Link to='/b' activeclassName='active'>B</Link></li>
<li><Link to='/c' activeclassName='active'>C</Link></li>
But I would like to get something similar to:
但我想得到类似的东西:
<li activeclassName='active'><IndexLink to='/'>A</IndexLink></li>
<li activeclassName='active'><Link to='/b'>B</Link></li>
<li activeclassName='active'><Link to='/c'>C</Link></li>
Thanks in advance
提前致谢
采纳答案by Marc Greenstock
You need to enclose your <li>
as a router aware component:
您需要将您的<li>
作为路由器感知组件附上:
import { Link, IndexLink } from 'react-router'
class NavItem extends React.Component {
render () {
const { router } = this.context
const { index, onlyActiveOnIndex, to, children, ...props } = this.props
const isActive = router.isActive(to, onlyActiveOnIndex)
const LinkComponent = index ? Link : IndexLink
return (
<li className={isActive ? 'active' : ''}>
<LinkComponent {...props}>{children}</LinkComponent>
</li>
)
}
}
Usage:
用法:
<ul>
<NavItem to='/' index={true}>Home</NavItem>
<NavItem to='/a'>A</NavItem>
</ul>
I took inspration from the react-router-bootstrap module, https://github.com/react-bootstrap/react-router-bootstrap/blob/master/src/LinkContainer.js. I didn't test it though so let me know how it goes.
我从 react-router-bootstrap 模块https://github.com/react-bootstrap/react-router-bootstrap/blob/master/src/LinkContainer.js获取灵感。我没有测试它,所以让我知道它是怎么回事。
回答by mpen
The other answers don't seem to work in React Router v4. Here's how you can do it:
其他答案似乎在 React Router v4 中不起作用。您可以这样做:
import React, {PropTypes} from 'react'
import {Route, Link} from 'react-router-dom'
import styles from './styles.less';
export default function NavItem({children, to, exact}) {
return (
<Route path={to} exact={exact} children={({match}) => (
<li className={match ? styles.activeRoute : null}>
<Link to={to}>{children}</Link>
</li>
)}/>
)
}
NavItem.propTypes = {
to: PropTypes.string.isRequired,
exact: PropTypes.bool,
children: PropTypes.node.isRequired,
};
回答by bryanyu
/**
* A navigation component
*/
import React, { Component } from 'react'
import { Link, IndexLink, withRouter } from 'react-router'
import styles from './styles.scss'
class NavItem extends Component {
render () {
const { router } = this.props
const { index, to, children, ...props } = this.props
let isActive
if( router.isActive('/',true) && index ) isActive = true
else isActive = router.isActive(to)
const LinkComponent = index ? IndexLink : Link
return (
<li className={isActive ? 'active' : ''}>
<LinkComponent to={to} {...props}>{children}</LinkComponent>
</li>
)
}
}
NavItem = withRouter(NavItem)
export default NavItem
Usage:
用法:
<ul className="nav nav-tabs">
<NavItem to='/home' index={true} >Home</NavItem>
<NavItem to='/about'>About</NavItem>
</ul>
回答by kenberkeley
{/* Make sure that `location` is injected into this component */}
<ul className="nav navbar-nav">
<li className={location.pathname === '/' && 'active'}>
<Link to='/'>
Home page
</Link>
</li>
<li className={location.pathname.startsWith('/about') && 'active'}>
<Link to='/about'>
About us
</Link>
</li>
</ul>
回答by Dimang Chou
In stead of using <Link />
, I use <NavLink />
and It works as well.
<Link />
我没有使用,而是使用<NavLink />
和 它也能工作。
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
//.....
export default class AppNav extends Component {
render (){
return (
<header>
<ul className="main-nav">
<li><NavLink activeClassName={"active"} exact={true} to="/">Home</NavLink></li>
<li><NavLink activeClassName={"active"} to="/about">About</NavLink></li>
<li><NavLink activeClassName={"active"} to="/courses">Courses</NavLink></li>
</ul>
</header>
);
}
}
回答by Matthew Berends
Great answer.
很好的答案。
Just change the following to get it working...
只需更改以下内容即可使其正常工作...
LinkComponent = index ? IndexLink : Link //If its true you want an IndexLink
//Also link needs to be...
<NavItem to="/" onlyActiveOnIndex index={true}>Home</NavItem>
回答by Erwin Mayer
Try with react-router-active-component.
尝试使用react-router-active-component。
I couldn't get any of the previous answers to easily work due to incompatibilities between react or typescript versions (this is definitely not a mature ecosystem), but this component did the trick, and can be applied to other elements than li
if needed:
由于 react 或 typescript 版本之间的不兼容,我无法轻松获得之前的任何答案(这绝对不是一个成熟的生态系统),但是这个组件成功了,并且可以应用于其他元素,li
除非需要:
import activeComponent from 'react-router-active-component'
let NavItem = activeComponent('li');
...
<NavItem to='/' onlyActiveOnIndex>Home</NavItem>
<NavItem to='/generate-keywords'>Generate keywords</NavItem>
回答by Cristi Draghici
Using react 15.1.0, react-router 2.5.0 and bootstrap 3.3 (this is less important), I developed this solution for making the links active:
使用 react 15.1.0、react-router 2.5.0 和 bootstrap 3.3(这不太重要),我开发了这个解决方案来激活链接:
npm install --save classnames
npm install --save classnames
npm install --save lodash
npm install --save lodash
The component:
组件:
import React from 'react';
import { Link, IndexLink } from 'react-router';
import _ from 'lodash';
import classnames from 'classnames';
class NavItem extends React.Component {
constructor(props) {
super(props);
// The default state
this.state = {
isActive: false,
unregisterRouteListener: false
};
// Binding for functions
this.locationHasChanged = this.locationHasChanged.bind(this);
}
componentDidMount() {
// Check if component is active on mount and add listener on route change
this.setState({
isActive: this.context.router.isActive(this.props.to, true),
unregisterRouteListener: this.context.router.listen(this.locationHasChanged)
});
}
componentWillUnmount() {
if (this.state.unregisterRouteListener) {
// Remove the listener
this.state.unregisterRouteListener();
}
// Reset the state
this.setState({
isActive: false,
unregisterRouteListener: false
});
}
// Update the state of the component, based on the router path
locationHasChanged() {
this.setState({
isActive: this.context.router.isActive(this.props.to, true)
});
}
render () {
let { index } = this.props;
let LinkComponent = index ? Link : IndexLink;
let newProps = _.omit(this.props, 'router');
return (
<li className={classnames('', this.state.isActive ? 'active' : '' )}>
<LinkComponent {...newProps}>
{this.props.children}
</LinkComponent>
</li>
);
}
}
NavItem.contextTypes = {
router: React.PropTypes.object
};
export default NavItem;
Usage:
用法:
<NavItem to="/list">List</NavItem>
I am a beginner with React, so the above solution surely needs improvements and might contain approach errors. However, it might also contain useful information or a starting point to those interested.
我是 React 的初学者,因此上述解决方案肯定需要改进,并且可能包含方法错误。但是,它也可能包含有用的信息或感兴趣的人的起点。
Any feedback or suggestions are more than welcome. Thanks! :)
任何反馈或建议都非常受欢迎。谢谢!:)
回答by Jernej Gori?ki
I'm using React Router v4.2 and I couldn't get the reference to the router object from the wrapping component, because the context is not available.
我正在使用 React Router v4.2,但无法从包装组件中获取对路由器对象的引用,因为上下文不可用。
This did not work:
这不起作用:
const { router } = this.context
I like @mpen's answer, but I'm using nested routes and I don't want to change the file where I have the routing component defined.
我喜欢@mpen 的回答,但我使用的是嵌套路由,我不想更改定义了路由组件的文件。
What I did is compared the location.pathname with to :
我所做的是将 location.pathname 与 to 进行比较:
const NavItem = withRouter(props => {
const { to, children, location } = props;
return (
<li className={location.pathname == to ? "active" : null}>
<Link to={to}>{children}</Link>
</li>
);
});
回答by Steve Breese
Using React Router v4, I only got it to work by including the <li>
tags within the NavLink component. The solutions which have the <li>
tags wrapping the links resulted in the HOME <li>
tag always having the active
class.
使用 React Router v4,我只是通过<li>
在 NavLink 组件中包含标签来让它工作。具有<li>
包装链接的标签的解决方案导致 HOME<li>
标签始终具有active
该类。
import React from 'react'
import { NavLink } from 'react-router-dom';
class Header extends React.Component {
render() {
return (
<div>
<header>
<nav>
<ul>
<NavLink activeClassName={"active"} exact={true} to="/"><li>Home</li></NavLink>
<NavLink activeClassName={"active"} to="/about"><li>About</li></NavLink>
<NavLink activeClassName={"active"} to="/courses"><li>Courses</li></NavLink>
</ul>
</nav>
</header>
</div>
)
}
}
export default Header
I adjusted the li
and a
CSS selectors accordingly.
我相应地调整了li
和a
CSS 选择器。