我refactorizing庞大的系统工程,其中阵营高阶元素 - 一个能走多远与传递道具
- 一些部件看起来非常相似
- 有文件的文件的looots(非常高的水平组件VS文件造粒)
我想过和寻找方法来处理这个问题在这里和那里,发现这个伟大的文章有关高阶组件(HOC) - 基本上是组件包装另一个组件。
https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e#.8vr464t20
我现在给你(A)三分之二八个类似的组件类型,我需要处理,比(B)的例如我会贴上我想出了代码将这八个文件合并为一个。最后,(C)将粘贴该统一组件的使用示例。
我会尽量保持一致,并且命名不会被域驱动(我不能在这里发布项目细节),但下面不同的代码片段中的相同名称将始终指向相同的组件和数据。否则我会指出它。
(A) - 类似的组件类型
1塔巴 - 简单的一
export default class TabA extends Component {
render() {
return (
<PageWrapper>
<Grid>
<GridItem xsSize="3">
<SmartComponent something={this.props.something }/>
</GridItem>
<GridItem xsSize="9">
<Tabs
permalink = { this.props.permalink }
history={ this.props.history }
activeTab={ Paths.somePath }
/>
<TabAContent
data={ this.props.data }
name={ this.props.name }
someValue={ this.props.someValue }
/>
</GridItem>
</Grid>
</PageWrapper>
);
}
}
注意SomeComponentA不采取任何的孩子也有。这里没有任何条件的渲染。
2.塔布 - 更复杂的一个
同样在这里,请注意renderSomeData方法有条件地呈现SmartComponentToBeConditionallyRendered也SomeComponentB对待儿童从道具。
export default class TabB extends Component {
renderSomeData() {
let someData = {
header: "Header text",
searchPlaceHolder: 'Search (name)',
buttonCaption: 'button caption'
};
return (
<SmartComponentToBeConditionallyRendered
type={ 'some_type' }
permalink={ this.props.permalink }
data={ someData }
/>
)
}
render() {
let { data } = this.props;
return (
<div>
<PageWrapper>
<Grid>
<GridItem xsSize="3">
<SmartComponent something={this.props.something}/>
</GridItem>
<GridItem xsSize="9">
<Tabs
permalink = { this.props.permalink }
history = { this.props.history }
activeTab = { Paths.somePage }
/>
<TabBContent data = { data }>
{this.props.children}
</TabBContent>
</GridItem>
</Grid>
</PageWrapper>
{
this.context.hasPermission('somePermission') ?
this.renderSomeData() :
null
}
</div>
)
}
static contextTypes = {
hasPermission: React.PropTypes.func.isRequired
}
}
这8个分量,我一开始写的 - 它们都代表三种可能性之一。 以上两图和可能性C,但C中的差异只是另一个有条件渲染的组件,所以不值得一提,因为它最终会降低传递道具中的更多标志。 -
这两个部件上述他们在不同:
- 样SomeComponentX的 - 代替X的有可能的A,B,而且C,d,E等在每个这八个类似的部件。 SomeComponentX中的每一个也都采用不同的道具。
- 路径。VALUE_HERE
- 如果SomeComponentX发生在任何的儿童或者不
- 如果他们有条件从renderSomeData方法
- 呈现数据如果是 - 该方法中定义someData变化以及
- 永久
- some_type
(B)我想出了什么
let availablePartials = {
PartialA: PartialA,
PartialB: PartialB,
PartialC: PartialC
}
export default class GenericTab extends Component {
renderSomeData() {
return (
<SomeData
type = { this.props.type }
permalink = { this.props.permalink }
data = { this.props.someData } //PASSED FROM PROPS NOW
/>
);
}
render() {
let tabContent = React.createElement(
availablePartials[this.props.partialView.name],
this.props.partialView.props,
this.props.renderChildren ? this.props.children : null
);
return (
<div>
<PageWrapper>
<Grid>
<GridItem xsSize="3">
<SmartComponent something = { this.props.permalink }/>
</GridItem>
<GridItem xsSize = "9">
<Tabs
permalink = { this.props.permalink }
history = { this.props.history }
activeTab = { this.props.activeTab }
/>
{ tabContent }
</GridItem>
</Grid>
</PageWrapper>
{
this.context.hasPermission(this.props.requiredPermission) && this.props.dataForSomeDataMethod ?
this.renderSomeData()
: null
}
</div>
)
}
static contextTypes = {
hasPermission: React.PropTypes.func.isRequired
}
};
CityPageTab.propTypes = {
permalink: PropTypes.string,
dataForSomeDataMethod: PropTypes.object,
type: PropTypes.string,
activeTab: PropTypes.string,
renderChildren: PropTypes.bool,
partialView: PropTypes.object,
requiredPermission: PropTypes.string
};
基本上是所有从道具构成。我唯一不喜欢的部分是availablePartials [this.props.partialView.name]。它需要开发者保持availablePartials对象的状态一致并且纠结一点。不是很好的解决方案,但仍然是最好的我到目前为止。
(C)新GenericTab使用例
componentThatUseGenericTabRenderMethod() {
let { valueA, valueB, valueC, history } = this.props;
let someData = {
header: 'header text',
searchPlaceHolder: 'Search (name)',
buttonCaption: 'buttonCaption'
}
return (
<GenericTab
partialView = {{
name: 'PartialA',
props: {
A: valueA,
B: valueB,
C: valueC,
history: history,
permalink: this.props.params.permalink
}
}}
permalink = { this.props.params.permalink }
activeTab = { Paths.somePath }
someData = { someData }
type = { 'SOME_TYPE' }
renderChildren = { false }
requiredPermission = { 'some_required_permision' }
/>
);
}
所以这是。用法有点复杂,但我摆脱了七个文件(并且摆脱文件是主要目标,因为它们太多了),并且将以类似的方式进一步推动它 - 通用文件。 具有通用性的东西 - 使用起来更加困难,但节省了大量空间。
项目利用终极版,所以不要太在意通过道具把树砍倒。他们总是只来自一些SmartParentComponent呈现GenericTab
下面是它的外观在页面上的可视化。 GenericTab负责渲染Tabs和TabContent部分。 是的,我知道这是很糟糕的解决方案,但我不负责它的体系结构。这里有很多事情需要重构,所问的仅仅是旅程中的一步。所以请让我们专注于所问的问题,而不是其他与此代码错误的事情。我知道了。:)
想我可以做的文章出来的,但我真的没有博客做:)。
请告诉我你的想法,建议升级,处理该问题的不同方式等
您可以加入的是什么选项卡看起来像一些视觉上的表现?这里很难理解整个事情,但我已经可以告诉你,你是组件负责渲染很多东西,你应该把它分成几个较小的组件。 – Pcriulan
嗯,唯一对我来说合理的分割方法是'renderSomeData'。我可以提取它,这是真的。除此之外,我在这里没有看到很多可能性。项目很混乱,有很多事情要做。是的,我会尝试编辑我的问题并添加可视化。 – azrahel
我相信这是有点可能的,当你编辑你的问题我想我可以帮你这么做 – Pcriulan