我在 URL 中有一组动态参数,例如用户区域设置,如下所示:
/en/homepage
在我的路由器配置 JSON 文件中,我有类似的内容:
/:locale/homepage
在 React Router 中直接替换这些参数的最佳方法是什么?
我提出了这个解决方案,在我看来,它与标准或便携式解决方案相去甚远:
const urlTemplate = '/:language/homepage';
const mappedUrl = pathToRegexp.compile(urlTemplate);
const url = mappedUrl({
'language': this.props.match.params.language
})
this.props.history.push(url);
如果组件由 withRouter (来自 React router 的 HOC )包装,我可以检索匹配参数并将其替换为 pathToRegexp (🐾pillarjs/path-to-regexp ),但是如果我需要在 a 中使用
<Link to={}>
无状态组件非常烦人。
有标准解决方案可以做到这一点吗?
提前谢谢您:)
当用户更改 Leaflet 地图视图时,我使用 React Router 的
generatePath
来更新路径 /map/:zoom/:lon/:lat/
。请注意,在我的例子中,我替换了路径而不是推送它。
import { generatePath } from 'react-router';
function updatePath(lat, lon, zoom) {
const path = generatePath(this.props.match.path, { lat, lon, zoom });
this.props.history.replace(path);
}
我使用一个函数,该函数使用正则表达式将路由路径的参数替换为函数的参数。
如果路线是:
'/:language/homepage'
该函数将用传递给函数的参数替换
:language
。
功能
这是替换路径中的值的函数:
function getRoute(path) {
let args = Array.prototype.slice.call(arguments, 1);
let count = -1;
return path.replace(/:[a-zA-Z?]+/g, function (match) {
count += 1;
return args[count] !== undefined ? args[count] : match;
});
};
这里的关键是正则表达式
/:[a-zA-Z?]+/g
,它只匹配以:
开头并包含a-z
和A-Z
之间的任何字符的字符串,这意味着当找到下一个/
时,它将完成匹配,所以它将替换所有像这样定义的参数。
这适用于我对简单参数的特定用法,但如果您需要向匹配的正则表达式添加更多字符,您可以这样做(例如数字、下划线等)。
用法
它的用法是这样的:
let newPath = getRoute('/:language/homepage', 'en');
结果将是:
'/en/homepage'
链接示例
它可以用于
Links
,如下所示:
<Link to={ getRoute('/:language/homepage', 'en') }>
rout中的多个参数e
它也接受多个参数:
getRoute('/:id/:language/homepage/:value', 123, 'en', 'myVal')
这将返回:
'/123/en/homepage/myVal'
React Router Dom参数替换功能。好处:
prefix
参数灵活用于其他库const repalacePathParams = (path, params, prefix = ':') => {
let newPath = path
Object.entries(params).forEach(([key, value]) => {
newPath = newPath.replace(prefix + key, value)
})
return newPath
}
console.log(repalacePathParams('/profile/:id/:name', { id: '111', name: 'tim' }))
//return '/profile/111/tim'
好吧,不确定您是否仍然对答案感兴趣,也不确定我的答案是否会对您有所帮助,但是...
如果您的路径很简单,例如您的示例(我的意思是,它们不包含正则表达式,例如
/:locale/kappa([a-z]{2})
),您可以编写这个独立于路由器的函数,您可以在其中手动处理路径并替换参数:)
function placeParams(pathRegex, params) {
var segments = pathRegex.split("/")
return segments.map(segment => {
var offset = segment.indexOf(":") + 1
if (!offset)
return segment
var key = segment.slice(offset)
return params[key]
}).join("/")
}
console.log(placeParams("/:locale/kappa", { locale: "en" }))
这是一个改进的答案,还允许您放置可选参数。
function placeParams(pathRegex, params) {
const segments = pathRegex.split("/");
return (
segments
.map((segment) => {
let offset = segment.indexOf(":?") + 1;
if (offset) {
let key = segment.slice(offset + 1);
return params[key];
}
offset = segment.indexOf(":") + 1;
if (!offset) return segment;
let key = segment.slice(offset);
return params[key];
})
.join("/")
// Remove trailing "/"
.replace(/\/+$/, "")
// Remove redundant "/"
.replace(/\/{2,}/, "/")
);
}
console.log(placeParams("/:locale/user/:?name/:?lastname", {
locale: "en",
name: "Nady",
lastname: "Shalaby"
}))