从 JSON 动态定义 ReactJS 路由
Posted
技术标签:
【中文标题】从 JSON 动态定义 ReactJS 路由【英文标题】:Dynamically Define ReactJS Routes from JSON 【发布时间】:2016-12-18 13:36:38 【问题描述】:我有一个全局 JSON 配置,其中包含各种配置数据,包括路由名称和我希望为路由呈现的组件。我想从这个 JSON 配置动态构建我的路由。我目前能够动态生成路由,但是,由于路由组件是 JSON 文件中的字符串,React 不喜欢它们并抛出下面的错误。对实现这一目标有何建议?
warning.js:44 Warning: Unknown props `history`, `location`, `params`, `route`, `routeParams`, `routes` on <Dashboard> tag. Remove these props from the element. For details, see https://f b.me/react-unknown-prop
in Dashboard
in RouterContext
in Router
相关JSON sn-p:
"routes" : [
"route_name" : "home",
"path" : "/",
"visible_in_menu" : true,
"menu_title" : "Home",
"menu_font_awesome_icon" : "fa fa-home",
"component" : "App",
"child_routes" : null
,
"route_name" : "analytics",
"path" : "/analytics",
"visible_in_menu" : true,
"menu_title" : "Analytics",
"menu_font_awesome_icon" : "fa fa-bar-chart",
"component" : "Dashboard",
"template" : null,
"child_routes" : [
"route_name" : "analytics_daily" ,
"path" : "/daily",
"visible_in_menu" : true,
"menu_title" : "Daily",
"component" : "Dashboard"
]
]
获取配置并动态构建路由的代码:
import React from 'react';
import ReactDOM from 'react-dom';
import Router, Route, Link, browserHistory from 'react-router'
import $ from 'jquery';
import App from './App';
import Dashboard from './Dashboard';
import SidebarMenu from './SidebarMenu';
import './index.css';
$.get("/routes_menu_config.json", bootstrapApplication);
function bootstrapApplication(config)
var dynamicRoutesJSX = buildDynamicRoutes(config);
// Add dynamic routes to app
ReactDOM.render((
<Router history=browserHistory>
dynamicRoutesJSX
</Router>
), document.getElementById('root'));
// Render sidebar menu
ReactDOM.render(
<SidebarMenu />,
document.getElementById('menu')
);
function buildDynamicRoutes(config)
var routeJSX = [];
for (let [index, route] of config.routes.entries())
routeJSX.push(<Route path=route.path components=route.component key=index/>);
return routeJSX;
我也尝试了路由的普通对象实例化,而不是使用 JSX,但它产生了同样的错误:
$.get("/routes_menu_config.json", bootstrapApplication);
function bootstrapApplication(config)
var dynamicRoutesJSX = buildDynamicRoutes(config);
// Add dynamic routes to app
ReactDOM.render(<Router history=browserHistory routes=dynamicRoutesJSX
// Render sidebar menu
ReactDOM.render(
<SidebarMenu />,
document.getElementById('menu')
);
function buildDynamicRoutes(config)
var routes = [];
// Iterate parent routes from config
for (var i=0; i<config.routes.length; i++)
var configParentRouteDefinition = config.routes[i];
// Create parent route definition
var parentRouteDefinition =
path : configParentRouteDefinition.path,
component: configParentRouteDefinition.component
;
// If there are child routes, add them to the definition
if(configParentRouteDefinition.child_routes)
// Track child routes
var childRoutes = [];
// Iterate child routes, generate definition
for(var j=0; j<configParentRouteDefinition.child_routes.length; j++)
var configChildRouteDefinition = configParentRouteDefinition.child_routes[j]
var childRouteDefinition =
path : configChildRouteDefinition.path,
component: configChildRouteDefinition.component
;
childRoutes.push(childRouteDefinition);
// Ad the definition to the parent route definition
parentRouteDefinition["childRoutes"] = childRoutes;
routes.push(parentRouteDefinition);
return routes;
【问题讨论】:
【参考方案1】:您需要创建一个组件注册表,以便您可以从它们的名称中查找组件引用:
import App from './App';
import Dashboard from './Dashboard';
const componentRegistry =
"App": App,
"Dashboard": Dashboard
<Route path=route.path components=componentRegistry[route.component] key=index/>;
【讨论】:
这行得通,谢谢。我希望有一种方法可以将字符串转换为实例化组件。 不幸的是,一个字符串告诉 React 渲染一个 html 节点,它不会在内部跟踪存在哪些组件,因此无法查找它们。【参考方案2】:如果您使用例如Webpack 无需导入所有组件即可获得您想要的结果。但是,您必须将路径传递给组件,而不是组件的名称。像这样:
json file:
"nav": [
"label": "HOME",
"route":
"url": "/",
"exact": true
,
"component":
"path": "home",
"name": "home"
createRoutes()
return this.props.data.nav.map((item: any, index: number) =>
let DynamicComponent = require('../../' + item.component.path + '/' + item.component.name).default;
return <Route key=index path=item.route.url
exact=item.route.exact
render=() => (<DynamicComponent key=item.component.name/>)/>
);
【讨论】:
【参考方案3】:这个对我有用
App.tsx
import routes from "./routes";
const App: React.FC = () =>
return (
<BrowserRouter>
<div>
<Switch>
routes.data.map((entry) => return (<Route ...entry/>))
</Switch>
</div>
</BrowserRouter>
);
;
export default App;
路由器.ts
const routes = data: [
key: "one",
path: "/three"
,
key: "two",
path: "/two"
]
export default routes;
【讨论】:
以上是关于从 JSON 动态定义 ReactJS 路由的主要内容,如果未能解决你的问题,请参考以下文章
如何从定义在和/或动态 id 元素名称的 JS 类外部渲染 ReactJS 组件?