Javascript React路由器v4面包屑
我正在努力实施 以下是我的路线:Javascript React路由器v4面包屑,javascript,reactjs,breadcrumbs,react-router-v4,Javascript,Reactjs,Breadcrumbs,React Router V4,我正在努力实施 以下是我的路线: const routes = { '/': 'Home', '/page1': 'Page 1', '/page2': 'Page 2' }; 我可以在我的应用程序中使用此库放置面包屑,但我有以下问题: Que#1: 当我在我的面包屑中点击Home时,我可以看到URL变为http://localhost:8080然而,浏览器仍然显示我所在的页面 Que#2: 当我从第1页导航到第2页时,url从http://
const routes = {
'/': 'Home',
'/page1': 'Page 1',
'/page2': 'Page 2'
};
我可以在我的应用程序中使用此库放置面包屑,但我有以下问题:
Que#1:
当我在我的面包屑中点击Home
时,我可以看到URL变为http://localhost:8080
然而,浏览器仍然显示我所在的页面
Que#2:
当我从第1页导航到第2页时,url
从http://localhost:8080/page1
至http://localhost:8080/page2
因此,面包屑显示更改为Home/Page 2
,而不是像Home/Page 1/Page 2
我知道这可能是因为url
在主机名之后有/page2
。但是,我可以实现如下显示:主页/Page 1/Page 2
下面是我的mainApp.jsx
中的代码:
<Router>
<div>
<Link to="/"><div className="routerStyle"><Glyphicon glyph="home" /></div></Link>
<Route exact path="/" component={LandingPage}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</div>
</Router>
如果我使用like-belowto来处理面包屑,那么我的第2页就会呈现在第1页下面:
<Router>
<div>
<Link to="/"><div className="routerStyle"><Glyphicon glyph="home" /></div></Link>
<Route exact path="/" component={LandingPage}/>
<Route path="/page1" component={Page1}/>
<Route path="/page1/page2" component={Page2}/>
</div>
</Router>
回答:
Que#1:无需将
元素包装在
应用程序的每个组件中。这可能是因为在每个组件中包含
元素会导致路由器
元素“嵌套”(注意,我们在登录页中也有路由器
标记);它不适用于react路由器v4
Que#2:请参考此处正式标记的答案(由下面的palsrealm回答)您的面包屑基于链接,并按设计工作。要显示页面,您需要设置一个
开关
,其中包含路由
s,当路径改变时,该开关将加载相应的组件。差不多
<Switch>
<Route path='/' component={Home}/>
<Route path='/page1' component={Page1}/>
<Route path='/page2' component={Page2}/>
</Switch>
这也可以通过HOC实现,HOC允许您使用route config对象来设置面包屑。我已经将其开源,但源代码如下:
Breadcrumbs.jsx
import React from 'react';
import { NavLink } from 'react-router-dom';
import { withBreadcrumbs } from 'withBreadcrumbs';
const UserBreadcrumb = ({ match }) =>
<span>{match.params.userId}</span>; // use match param userId to fetch/display user name
const routes = [
{ path: 'users', breadcrumb: 'Users' },
{ path: 'users/:userId', breadcrumb: UserBreadcrumb},
{ path: 'something-else', breadcrumb: ':)' },
];
const Breadcrumbs = ({ breadcrumbs }) => (
<div>
{breadcrumbs.map(({ breadcrumb, path, match }) => (
<span key={path}>
<NavLink to={match.url}>
{breadcrumb}
</NavLink>
<span>/</span>
</span>
))}
</div>
);
export default withBreadcrumbs(routes)(Breadcrumbs);
以下组件应该在任何深度返回面包屑,主页上除外(出于明显的原因)。你不需要面包屑。我的第一次公开贡献,所以如果我遗漏了一个重要部分,如果有人能指出这一点,那就太好了。我添加了
»代码>用于碎屑分割,但显然可以根据需要进行更新
import React from 'react'
import ReactDOM from 'react-dom'
import { Route, Link } from 'react-router-dom'
// styles
require('./styles/_breadcrumbs.scss')
// replace underscores with spaces in path names
const formatLeafName = leaf => leaf.replace('_', ' ')
// create a path based on the leaf position in the branch
const formatPath = (branch, index) => branch.slice(0, index + 1).join('/')
// output the individual breadcrumb links
const BreadCrumb = props => {
const { leaf, index, branch } = props,
leafPath = formatPath(branch, index),
leafName = index == 0 ? 'home' : formatLeafName(leaf),
leafItem =
index + 1 < branch.length
? <li className="breadcrumbs__crumb">
<Link to={leafPath}>{leafName}</Link>
<span className="separator">»</span>
</li>
: <li className="breadcrumbs__crumb">{leafName}</li>
// the slug doesn't need a link or a separator, so we output just the leaf name
return leafItem
}
const BreadCrumbList = props => {
const path = props.match.url,
listItems =
// make sure we're not home (home return '/' on url)
path.length > 1
&& path
// create an array of leaf names
.split('/')
// send our new array to BreadCrumb for formating
.map((leaf, index, branch) =>
<BreadCrumb leaf={leaf} index={index} branch={branch} key={index} />
)
// listItem will exist anywhere but home
return listItems && <ul className="breadcrumbs">{listItems}</ul>
}
const BreadCrumbs = props =>
<Route path="/*" render={({ match }) => <BreadCrumbList match={match} />} />
export default BreadCrumbs
从“React”导入React
从“react dom”导入react dom
从“react router dom”导入{Route,Link}
//风格
需要('./样式/_breadcrumbs.scss'))
//将路径名中的下划线替换为空格
const formatLeafName=leaf=>leaf.replace(“”,“”)
//基于分支中的叶位置创建路径
const formatPath=(branch,index)=>branch.slice(0,index+1).join(“/”)
//输出各个面包屑链接
常量面包屑=道具=>{
const{leaf,index,branch}=props,
叶路径=格式化路径(分支、索引),
leafName=索引==0?“主”:formatLeafName(叶),
叶项=
索引+1<分支长度
?
{leafName}
&拉阔;
:{leafName}
//slug不需要链接或分隔符,因此我们只输出叶名称
退货项目
}
常量面包屑列表=道具=>{
const path=props.match.url,
列表项=
//确保我们不在家(url上的主页返回“/”)
路径长度>1
&&路径
//创建一个叶名称数组
.split(“/”)
//将新数组发送到BreadCrumb进行格式化
.map((叶、索引、分支)=>
)
//listItem将存在于除home之外的任何位置
返回listItems&&{listItems}
}
常量面包屑=道具=>
} />
导出默认面包屑
有任何反应代码吗?这与前面给出的URL相同,谢谢。我不认为这是你能从盒子里拿出来的东西。你必须自己实现逻辑;可能是通过存储上次访问的url,并使用Link或NavLink组件手动将其添加到面包屑中。@palsrealm是正确的。您需要一个开关
。另外,如果您想同时捕获“/page1”和“/page1/page2”,您需要“/page1”的路由上的exact
。用您想要使用的路由器的代码更新我的答案。正如@Luke M WillisThanks所指定的那样,现在通过使用“精确”,两个页面在一个屏幕上呈现的问题得到了解决。但是,当我单击面包屑时,只会更改浏览器URL,而不会更改内容。有什么线索吗?当浏览器url按预期更改时,这意味着您的链接工作正常。当内容没有呈现时,这意味着应该在该url呈现的组件没有呈现,您需要检查组件和路由。
import React from 'react';
import { matchPath, withRouter } from 'react-router';
const renderer = ({ breadcrumb, match }) => {
if (typeof breadcrumb === 'function') { return breadcrumb({ match }); }
return breadcrumb;
};
export const getBreadcrumbs = ({ routes, pathname }) => {
const matches = [];
pathname
.replace(/\/$/, '')
.split('/')
.reduce((previous, current) => {
const pathSection = `${previous}/${current}`;
let breadcrumbMatch;
routes.some(({ breadcrumb, path }) => {
const match = matchPath(pathSection, { exact: true, path });
if (match) {
breadcrumbMatch = {
breadcrumb: renderer({ breadcrumb, match }),
path,
match,
};
return true;
}
return false;
});
if (breadcrumbMatch) {
matches.push(breadcrumbMatch);
}
return pathSection;
});
return matches;
};
export const withBreadcrumbs = routes => Component => withRouter(props => (
<Component
{...props}
breadcrumbs={
getBreadcrumbs({
pathname: props.location.pathname,
routes,
})
}
/>
));
import React from 'react'
import ReactDOM from 'react-dom'
import { Route, Link } from 'react-router-dom'
// styles
require('./styles/_breadcrumbs.scss')
// replace underscores with spaces in path names
const formatLeafName = leaf => leaf.replace('_', ' ')
// create a path based on the leaf position in the branch
const formatPath = (branch, index) => branch.slice(0, index + 1).join('/')
// output the individual breadcrumb links
const BreadCrumb = props => {
const { leaf, index, branch } = props,
leafPath = formatPath(branch, index),
leafName = index == 0 ? 'home' : formatLeafName(leaf),
leafItem =
index + 1 < branch.length
? <li className="breadcrumbs__crumb">
<Link to={leafPath}>{leafName}</Link>
<span className="separator">»</span>
</li>
: <li className="breadcrumbs__crumb">{leafName}</li>
// the slug doesn't need a link or a separator, so we output just the leaf name
return leafItem
}
const BreadCrumbList = props => {
const path = props.match.url,
listItems =
// make sure we're not home (home return '/' on url)
path.length > 1
&& path
// create an array of leaf names
.split('/')
// send our new array to BreadCrumb for formating
.map((leaf, index, branch) =>
<BreadCrumb leaf={leaf} index={index} branch={branch} key={index} />
)
// listItem will exist anywhere but home
return listItems && <ul className="breadcrumbs">{listItems}</ul>
}
const BreadCrumbs = props =>
<Route path="/*" render={({ match }) => <BreadCrumbList match={match} />} />
export default BreadCrumbs