Javascript React/JSX动态组件名称
我正在尝试根据组件的类型动态渲染组件 例如:Javascript React/JSX动态组件名称,javascript,reactjs,react-jsx,Javascript,Reactjs,React Jsx,我正在尝试根据组件的类型动态渲染组件 例如: var type = "Example"; var ComponentName = type + "Component"; return <ComponentName />; // Returns <examplecomponent /> instead of <ExampleComponent /> var type=“示例”; var ComponentName=类型+“组件”; 返回; //返回而不是
var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />;
// Returns <examplecomponent /> instead of <ExampleComponent />
var type=“示例”;
var ComponentName=类型+“组件”;
返回;
//返回而不是
我尝试了这里提出的解决方案
这在编译时给了我一个错误(使用browserify进行gulp)。在我使用数组语法的地方,它需要XML
我可以通过为每个组件创建一个方法来解决这个问题:
newExampleComponent() {
return <ExampleComponent />;
}
newComponent(type) {
return this["new" + type + "Component"]();
}
newExampleComponent(){
返回;
}
新成员(类型){
返回此[“新”+类型+“组件”]();
}
但这意味着我创建的每个组件都有一个新方法。对于这个问题,必须有一个更优雅的解决方案
我很乐意接受建议。我想出了一个新的解决方案。请注意,我正在使用ES6模块,因此我需要该类。您还可以定义一个新的React类
var components = {
example: React.createFactory( require('./ExampleComponent') )
};
var type = "example";
newComponent() {
return components[type]({ attribute: "value" });
}
编译为React.createElement(MyComponent,{})
,它需要字符串(HTML标记)或函数(ReactClass)作为第一个参数
您可以将组件类存储在一个名称以大写字母开头的变量中。看
如果您的组件是全局的,您只需执行以下操作:
var nameOfComponent=“SomeComponent”;
createElement(窗口[nameOfComponent],{})代码>我使用了一种有点不同的方法,因为我们总是知道我们的实际组件,所以我想应用switch case。
在我的案例中,组件的总数量大约为7-8
getSubComponent(name) {
let customProps = {
"prop1" :"",
"prop2":"",
"prop3":"",
"prop4":""
}
switch (name) {
case "Component1": return <Component1 {...this.props} {...customProps} />
case "Component2": return <Component2 {...this.props} {...customProps} />
case "component3": return <component3 {...this.props} {...customProps} />
}
}
getSubComponent(名称){
让customProps={
“第1项建议”:“,
“第二项建议”:“第二项建议”,
“第三项建议”:“第三项建议”,
“prop4”:”
}
交换机(名称){
案例“组件1”:返回
案例“组件2”:返回
案例“组件3”:返回
}
}
编辑:其他答案更好,请参见注释
我用这种方法解决了同样的问题:
...
render : function () {
var componentToRender = 'component1Name';
var componentLookup = {
component1Name : (<Component1 />),
component2Name : (<Component2 />),
...
};
return (<div>
{componentLookup[componentToRender]}
</div>);
}
...
。。。
渲染:函数(){
var componentorender='component1Name';
变量组件查找={
组件1名称:(),
组件2名称:(),
...
};
返回(
{componentLookup[componentToRender]}
);
}
...
对于包装器组件,一个简单的解决方案是直接使用React.createElement
(使用ES6)
有关如何处理此类情况的官方文件可在此处查阅:
基本上它说:
错:
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// Wrong! JSX type can't be an expression.
return <components[props.storyType] story={props.story} />;
}
从“React”导入React;
从“/stories”导入{PhotoStory,VideoStory};
常数分量={
照片:PhotoStory,
录像:录像故事
};
功能故事(道具){
//错误!JSX类型不能是表达式。
返回;
}
正确:
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// Correct! JSX type can be a capitalized variable.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
从“React”导入React;
从“/stories”导入{PhotoStory,VideoStory};
常数分量={
照片:PhotoStory,
录像:录像故事
};
功能故事(道具){
//正确!JSX类型可以是大写的变量。
const SpecificStory=组件[props.storyType];
返回;
}
suspess我们希望通过动态组件加载访问各种视图。下面的代码给出了一个工作示例,说明如何通过使用从url的搜索字符串解析的字符串来实现这一点
假设我们希望使用以下url路径访问具有两个唯一视图的页面“snozberrys”:
'http://localhost:3000/snozberrys?aComponent'
及
我们这样定义视图的控制器:
import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Route
} from 'react-router-dom'
import AComponent from './AComponent.js';
import CoBComponent sole from './BComponent.js';
const views = {
aComponent: <AComponent />,
console: <BComponent />
}
const View = (props) => {
let name = props.location.search.substr(1);
let view = views[name];
if(view == null) throw "View '" + name + "' is undefined";
return view;
}
class ViewManager extends Component {
render() {
return (
<Router>
<div>
<Route path='/' component={View}/>
</div>
</Router>
);
}
}
export default ViewManager
ReactDOM.render(<ViewManager />, document.getElementById('root'));
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule);
import React,{Component}来自'React';
从“react dom”导入react dom
进口{
BrowserRouter作为路由器,
路线
}从“反应路由器dom”
从“./AComponent.js”导入组件;
从“/BComponent.js”导入组件;
常量视图={
A成分:,
慰问:
}
常量视图=(道具)=>{
让name=props.location.search.substr(1);
让视图=视图[名称];
如果(view==null)抛出“view'”+name+“'未定义”;
返回视图;
}
类ViewManager扩展组件{
render(){
返回(
);
}
}
导出默认视图管理器
ReactDOM.render(,document.getElementById('root'));
应该有一个容器,将组件名称映射到应该动态使用的所有组件。组件类应该在容器中注册,因为在模块化环境中,并没有一个地方可以访问它们。组件类在未明确指定的情况下无法通过其名称进行标识,因为函数name
在生产中已缩小
组件映射
它可以是普通对象:
class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
普通对象更合适,因为它得益于属性速记
桶模块
具有命名导出的映射可以充当以下映射:
// Foo.js
export class Foo extends React.Component { ... }
// dynamic-components.js
export * from './Foo';
export * from './Bar';
// some module that uses dynamic component
import * as componentsMap from './dynamic-components';
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
装饰器可以用作具有功能组件的高阶组件:
const Bar = props => ...;
Bar.displayName = 'Bar';
export default dynamic(Bar);
使用代替随机属性也有利于调试。假设我们有一个标志
,与状态
或道具
没有区别:
import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';
~~~
const Compo = flag ? ComponentOne : ComponentTwo;
~~~
<Compo someProp={someValue} />
import ComponentOne from./ComponentOne';
从“./ComponentTwo”导入ComponentTwo;
~~~
const Compo=标志?组件一:组件二;
~~~
使用flagComponent
填充ComponentOne
或ComponentTwo
中的一个,然后Component
可以像React组件一样工作。在组件映射的所有选项中,我还没有找到使用ES6短语法定义映射的最简单方法:
从“React”导入React
从“/stories”导入{PhotoStory,VideoStory}
常数分量={
摄影记录,
录像故事,
}
功能故事(道具){
//鉴于props.story包含“PhotoStory”或“VideoStory”
const SpecificStory=组件[props.story]
返回
}
拥有一张地图,有大量的组件,看起来一点都不好。事实上,我很惊讶没有人提出这样的建议:
import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Route
} from 'react-router-dom'
import AComponent from './AComponent.js';
import CoBComponent sole from './BComponent.js';
const views = {
aComponent: <AComponent />,
console: <BComponent />
}
const View = (props) => {
let name = props.location.search.substr(1);
let view = views[name];
if(view == null) throw "View '" + name + "' is undefined";
return view;
}
class ViewManager extends Component {
render() {
return (
<Router>
<div>
<Route path='/' component={View}/>
</div>
</Router>
);
}
}
export default ViewManager
ReactDOM.render(<ViewManager />, document.getElementById('root'));
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule);
当我需要以json数组的形式呈现大量加载的组件时,这一点确实帮助了我。随着的介绍,我们现在可以使用真正的动态方法导入组件并重新加载
const componentsMap = {};
function dynamic(Component) {
if (!Component.displayName)
throw new Error('no name');
componentsMap[Component.displayName] = Component;
return Component;
}
...
@dynamic
class Foo extends React.Component {
static displayName = 'Foo'
...
}
const Bar = props => ...;
Bar.displayName = 'Bar';
export default dynamic(Bar);
import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';
~~~
const Compo = flag ? ComponentOne : ComponentTwo;
~~~
<Compo someProp={someValue} />
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule);
import React, { lazy, Suspense } from 'react';
const App = ({ componentName, ...props }) => {
const DynamicComponent = lazy(() => import(`./${componentName}`));
return (
<Suspense fallback={<div>Loading...</div>}>
<DynamicComponent {...props} />
</Suspense>
);
};