Javascript react组件是否可以有多个子内容区域?
假设我有一个简单的反应组件:Javascript react组件是否可以有多个子内容区域?,javascript,reactjs,Javascript,Reactjs,假设我有一个简单的反应组件: import React from 'react'; import styles from "./index.css"; export default React.createClass({ render: function() { return ( <header className={styles.root}> // area for child content {this.props.chi
import React from 'react';
import styles from "./index.css";
export default React.createClass({
render: function() {
return (
<header className={styles.root}>
// area for child content
{this.props.children}
</header>
);
}
});
从“React”导入React;
从“/index.css”导入样式;
导出默认的React.createClass({
render:function(){
返回(
//子内容区域
{this.props.children}
);
}
});
现在让我们假设,我想要两个区域,而不是任何子组件的一个区域,如下所示:
import React from 'react';
import styles from "./index.css";
export default React.createClass({
render: function() {
return (
<header className={styles.root}>
<div className={styles.logo}>
// logo children here
</div>
<div>
// navigation children here
</div>
</header>
);
}
});
从“React”导入React;
从“/index.css”导入样式;
导出默认的React.createClass({
render:function(){
返回(
//这里有儿童标志
//这里的孩子们
);
}
});
我知道我可以使用属性,但对于大量html内容来说,这不是很优雅。如何在react中以类似于(例如)在swig中的方式实现这一点
命名块的示例:
{% extends 'layout.html' %}
{% block title %}My Page{% endblock %}
{% block head %}
{% parent %}
<link rel="stylesheet" href="custom.css">
{% endblock %}
{% block content %}
<p>This is just an awesome page.</p>
{% endblock %}
{%extends'layout.html%}
{%block title%}我的页面{%endblock%}
{%block head%}
{%parent%}
{%endblock%}
{%block content%}
这只是一个很棒的页面
{%endblock%}
您可以看到,这些块可以通过引用它们的名称来使用,从而允许“生成”多个内容区域。我希望在react中有一种类似的优雅方式来实现这一点,因为它使组件非常可组合
Make seperate components Donot use props to pass components as children.
something like this.
//header.js
import React from 'react';
import styles from "./index.css";
export default React.createClass({
getComponent(key) {
return this.props.children.filter( (comp) => {
return comp.key === key;
});
}
render: function() {
return (
<header className={styles.root}>
<div className={styles.logo}>
{this.getComponent('logo')}
</div>
<div>
{this.getComponent('navbar'}
</div>
</header>
);
}
});
从“React”导入React;
从“/index.css”导入样式;
导出默认的React.createClass({
getComponent(键){
返回此.props.children.filter((comp)=>{
返回comp.key==key;
});
}
render:function(){
返回(
{this.getComponent('logo')}
{this.getComponent('navbar'}
);
}
});
//app.js
export default React.createClass({
render: function() {
return (
<Header>
<Logo key="logo"/>
<Navbar key="navbar"/>
</Header>
);
}
});
export default React.createClass({
render:function(){
返回(
);
}
});
从“React”导入React,{Component};
从“/index.css”导入样式;
从“/components/Logo”导入徽标;
从“/components/Logo”导入导航栏;
类Comp扩展组件{
render(){
返回(
);
}
}
类头扩展组件{
render(){
设{top,right}=this.props;
返回(
{top&&}
{右&&}
);
}
}
您可以将道具视为儿童,因为从技术上讲,儿童只是另一种道具。这种方法没有错——React贡献者自己建议您这样做()
此外,如果您在一个大型工程师团队中工作,我还建议您将这些道具的命名方式以及它们的标准行为标准化——它们只是普通内容还是可以传递参数的回调。可以帮助您做到这一点。因此,组件的代码可以如下所示:
//header.jsx
从“React”导入React;
使用“react占位符”中的窗口导入;
@带图标('徽标','导航')
导出默认类标头扩展React.Component{
render(){
返回(
{this.props.header()}
{this.props.navigation('home')}
);
}
}
这就是如何嵌入该组件
//app.jsx
从“Header.jsx”导入头
导出默认类标头扩展React.Component{
render(){
返回(
{
返回
}}
/>
);
}
}
这个问题启发了我。以下是我的方法:
第一个子组件:TestA.tsx
import * as React from 'react';
export default class TestA extends React.Component {
render () {
return (
<div className="TestA">{this.props.children}</div>
)
}
}
import * as React from 'react';
export default class TestB extends React.Component {
render () {
return (
<div className="TestB">{this.props.children}</div>
)
}
}
import * as React from 'react';
type TestABProps = {
children: React.ReactNode;
}
export default class TestAB extends React.Component<TestABProps> {
//Loop through React nodes in children and get all instances of the specified component
getComp( comp: string ): null | React.ReactNode | React.ReactNode[] {
if( this.props.children instanceof Array ) {
let nodes: React.ReactNode[] = [];
for( let child of this.props.children ) {
if( ((child as React.ReactElement)?.type as Function)?.name == comp ) {
nodes.push( child );
}
}
return nodes.length > 1 ? nodes : nodes[0];
}
return null;
}
render () {
return (
<div className="AB">
<div className ="A">
{this.getComp("TestA")}
</div>
<div>This is a DIV between the components</div>
<div className ="B">
{this.getComp("TestB")}
</div>
</div>
)
}
}
使用非常简单和直观。不需要键或其他任何东西,只需插入您的子组件而不需要奇怪的语法
结果HTML
<div class="AB">
<div class="A">
<div class="TestA">Foo</div>
<div class="TestA">Foobar</div>
</div>
<div>This is a DIV between the components</div>
<div class="B">
<div class="TestB">Bar</div>
</div>
</div>
福
福巴
这是组件之间的一个DIV
酒吧
请注意,您可以按任意顺序插入TestAB的子项-它们将被插入到正确的位置
所有这些当然都可以改进,您可以根据自己的需要进行调整。例如,如果您放置TestA或TestB以外的任何子组件,它们将不会显示,这将是我的第一个改进。当您说“我知道我可以使用属性”时-你是说道具吗?那为什么不优雅呢?是的,标签
中定义的属性。你的命名块示例看起来像Django,而不是swig?因此组件基本上只能包装一个实体?无法将多个内容传递给它?因为这意味着我必须进行大量深入研究组件,以确定它们由哪些子组件组成,而如果我可以传递任意数量的内容区域,理论上我可以在单个区域中对组件/html的整个排列进行概述。啊,好吧,这与我所寻找的有点接近。尽管我可以看出这可能会令人困惑,因为没有指示哪个子级去哪里(除非您对其进行注释或使用声明性组件名称),而且很容易不小心切换顺序。swig中的命名块非常明显地显示了哪些内容会被放在哪里。我猜这在react中没有等价物?类似于命名子对象而不是通过数组索引注入它们?检查代码现在我为组件徽标和导航栏添加了一个键,现在我可以循环使用这些道具了。c孩子们找到我合适的方法啊,好的,太好了!谢谢你的回答!更干净的方法!这是正确的解决方案即使react文档建议采取这种方法也是错误的声明关于不要使用道具作为孩子传递组件
“道具和构图为您提供了以明确和安全的方式定制组件外观和行为所需的所有灵活性
<TestAB>
<TestA>Foo</TestA>
<TestB>Bar</TestB>
<TestA>Foobar</TestA>
</TestAB>
<div class="AB">
<div class="A">
<div class="TestA">Foo</div>
<div class="TestA">Foobar</div>
</div>
<div>This is a DIV between the components</div>
<div class="B">
<div class="TestB">Bar</div>
</div>
</div>