需要特定包含组件的反应组件的模式
Pattern for react components that require specific contained components
编写嵌套特定子组件的组件的惯用 React 方法是什么?我知道如何编写一个简单包装 props.children
的组件,就像 React 自己的文档中的这个例子:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
但是如果我想创建一对可以像这样使用的组件怎么办:
<TabSet>
<Tab name="Mammals">
content for <b>warm blooded</b> creatures here
</Tab>
<Tab name="Fish">
content for <b>cold blooded</b> creatures here
</Tab>
</TabSet>
这是我对 TabSet
的初始实现(使用 reactstrap),经过简化以删除样式、选定选项卡管理以及与此问题无关的其他内容。
import React, {Fragment, Component} from 'react';
import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
export default class TabSet extends Component {
render(props) {
return (
<Fragment>
<Nav tabs>
{props.children.map((tab,i) =>
<NavItem key={i}>
<NavLink>
{ tab.name }
</NavLink>
</NavItem>
)}
</Nav>
<TabContent>
{props.children.map((tab,i) =>
<TabPane key={i} tabId={i}>
{ tab.children }
</TabPane>
)}
</TabContent>
</Fragment>
);
}
}
我卡住的地方是如何实现 Tab
组件。从逻辑上讲,它是 TabSet
组件的一部分——它永远不应该独立存在。它的实现应该非常简单,因为它实际上什么都不做——它只是 name
属性和子元素的容器。
所以,这里有几个问题:
- 我应该为
Tab
组件创建一个单独的 JS 文件,还是简单到我应该将其作为 TabSet
组件实现的一部分导出?如果是后者,怎么办?
- 在使用
TabSet
的 类 中,我是否需要两个 import
语句,或者有什么方法可以同时导入 TabSet
和 Tab
用一个 import
,有点像 import React, {Fragment} from 'react'
行得通吗?如果是后者,那么 TabSet.js 中的导出语句将如何显示?
很抱歉这个问题很明显——我是 React 和 ES6 的新手。
在您使用 export default class ...
的地方,您实际上可以在此处导出您自己的 object。考虑到这一点,您可以执行以下操作:
const TabSet = props => (
<Your Tabset markup here>
)
const Tab = props => (
<Your Tab markup here>
)
export {
Tabset,
Tab
}
这样做可以让您在一行中导入两个组件:
import { Tabset, Tab } from 'wherever'
虽然这是一种方法,虽然您认为 Tab
很简单,但我仍然相信它们属于自己的文件。因此,只需为 Tabset
和 Tab
创建两个 class 文件,然后创建名为 tabs.js
之类的第三个文件。它应该包含两者的 link,例如:
import Tabset from './tabset'
import Tab from './tab'
export {
Tabset,
Tab
}
这样您就可以为每个组件指定文件,并且可以将它们作为单个导入来导入。
此外,如果您使用反应的 PropTypes
能力,您可以限制 Tabset
的 children 实际上是您的标签。 Here 是概述,但作为示例,您可以执行以下操作:
// untested
static propTypes = {
children: PropTypes.arrayOf(PropTypes.instanceOf(Tab))
}
您必须将 Tab
组件导入 set 组件才能执行此操作。
如果该组件仅在另一个组件的上下文中使用,则将它们放在同一个模块中是合乎逻辑的,许多库都这样做。实现此目的的方法是在不使用 default
的情况下使用多个 export
语句。您可以根据需要使用一个 export default
和任意多个 export
语句。像这样
export default class TabSet
...
export class Tab
并导入
import TabSet, {Tab} from './Tab'
一般语法是
import defaultExport, { namedExport1, namedExport2 } from "module"
语法可能看起来有点混乱here is the reference
编写嵌套特定子组件的组件的惯用 React 方法是什么?我知道如何编写一个简单包装 props.children
的组件,就像 React 自己的文档中的这个例子:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
但是如果我想创建一对可以像这样使用的组件怎么办:
<TabSet>
<Tab name="Mammals">
content for <b>warm blooded</b> creatures here
</Tab>
<Tab name="Fish">
content for <b>cold blooded</b> creatures here
</Tab>
</TabSet>
这是我对 TabSet
的初始实现(使用 reactstrap),经过简化以删除样式、选定选项卡管理以及与此问题无关的其他内容。
import React, {Fragment, Component} from 'react';
import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
export default class TabSet extends Component {
render(props) {
return (
<Fragment>
<Nav tabs>
{props.children.map((tab,i) =>
<NavItem key={i}>
<NavLink>
{ tab.name }
</NavLink>
</NavItem>
)}
</Nav>
<TabContent>
{props.children.map((tab,i) =>
<TabPane key={i} tabId={i}>
{ tab.children }
</TabPane>
)}
</TabContent>
</Fragment>
);
}
}
我卡住的地方是如何实现 Tab
组件。从逻辑上讲,它是 TabSet
组件的一部分——它永远不应该独立存在。它的实现应该非常简单,因为它实际上什么都不做——它只是 name
属性和子元素的容器。
所以,这里有几个问题:
- 我应该为
Tab
组件创建一个单独的 JS 文件,还是简单到我应该将其作为TabSet
组件实现的一部分导出?如果是后者,怎么办? - 在使用
TabSet
的 类 中,我是否需要两个import
语句,或者有什么方法可以同时导入TabSet
和Tab
用一个import
,有点像import React, {Fragment} from 'react'
行得通吗?如果是后者,那么 TabSet.js 中的导出语句将如何显示?
很抱歉这个问题很明显——我是 React 和 ES6 的新手。
在您使用 export default class ...
的地方,您实际上可以在此处导出您自己的 object。考虑到这一点,您可以执行以下操作:
const TabSet = props => (
<Your Tabset markup here>
)
const Tab = props => (
<Your Tab markup here>
)
export {
Tabset,
Tab
}
这样做可以让您在一行中导入两个组件:
import { Tabset, Tab } from 'wherever'
虽然这是一种方法,虽然您认为 Tab
很简单,但我仍然相信它们属于自己的文件。因此,只需为 Tabset
和 Tab
创建两个 class 文件,然后创建名为 tabs.js
之类的第三个文件。它应该包含两者的 link,例如:
import Tabset from './tabset'
import Tab from './tab'
export {
Tabset,
Tab
}
这样您就可以为每个组件指定文件,并且可以将它们作为单个导入来导入。
此外,如果您使用反应的 PropTypes
能力,您可以限制 Tabset
的 children 实际上是您的标签。 Here 是概述,但作为示例,您可以执行以下操作:
// untested
static propTypes = {
children: PropTypes.arrayOf(PropTypes.instanceOf(Tab))
}
您必须将 Tab
组件导入 set 组件才能执行此操作。
如果该组件仅在另一个组件的上下文中使用,则将它们放在同一个模块中是合乎逻辑的,许多库都这样做。实现此目的的方法是在不使用 default
的情况下使用多个 export
语句。您可以根据需要使用一个 export default
和任意多个 export
语句。像这样
export default class TabSet
...
export class Tab
并导入
import TabSet, {Tab} from './Tab'
一般语法是
import defaultExport, { namedExport1, namedExport2 } from "module"
语法可能看起来有点混乱here is the reference