数据应尽可能靠近树的根部进行控制。这样做提供了一些简单的优化,因为您只传递了您需要的内容。
这将冒泡到您控制某些生命周期组件的位置。正如 mgmcdermott 所提到的,很多生命周期组件实际上取决于您在做什么,但最好的情况是拥有最简单、最愚蠢的组件。
在我的大多数项目中,在我的 react 目录中,我有components/
和views/
. 视图应该尽可能多地完成繁重的工作,这始终是我的偏好。话虽如此,我已经构建了许多使用生命周期方法(如componentDidMount
、componentWillMount
、 )的组件componentWillUnmount
,但我通常尝试在我的视图中隔离更新,因为在我看来,它们的工作之一是控制数据流。这意味着componentShouldUpdate
会住在那里。就我个人而言,我认为componentShouldUpdate
这纯粹是最终的优化,而且我只在重新渲染期间遇到较大性能问题的情况下才使用它。
我不太确定我理解你的“继承自React.Component
”问题。如果你问要不要使用纯函数,es6 class
,或者React.createClass
,我不知道有标准规则,但保持一致是好的。
要解决您是否正在处理行为或演示,行为是点击,但重新绘制是演示。您的行为可能很好地存在于您的Tab
组件中,在您的Tabs
视图中重新绘制。 Tabs
view 从 redux 传递您的方法,将当前活动的选项卡设置为您的各个Tab
组件,然后可以通过 redux 发送选项卡切换的行为,以便您可以进行演示componentShouldUpdate
。那有意义吗?
因此,您mapToDispatch
在容器中的方法将有一个函数来设置您的活动选项卡,我们称之为activateTab(idx)
,它采用基于 0 的选项卡索引。您的容器将其传递给您控制的包含组件,即views/Tabs
,并将该方法传递给components/Tab
。 components/Tab
将有一个onClick
方法侦听您的一个 DOM 元素,然后调用this.props.activateTab(myIndex)
(您也可以将 activateTab 的绑定版本传递给components/Tab
它,因此它不必知道它自己的索引),这会触发 redux,然后将您的成数据views/Tabs
,它可以处理一个componentShouldUpdate
基于从终极版的数据。
扩展编辑:由于这被标记为已接受,我会将我的代码示例吹成对普通人可用的东西。
顺便说一句,我不会写太多 redux,因为这可能非常依赖于应用程序,但我假设您有一个activeTabIdx
挂断父级的状态。
容器/TabExample.jsx
import { connect } from 'react-redux'
import Tabs from 'views/Tabs.js'
const mapStateToProps = function (state) {
return {
activeTabIdx: state.activeTabIdx
// And whatever else you have...
}
}
const mapDispatchToProps = function (dispatch) {
return {
activateTab: function (idx) {
dispatch({
action: 'ACTIVATE_TAB_IDX',
idx: idx
}) // You probably want this in a separate actions/tabs.js file...
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Tabs)
视图/Tabs.js
import React, { createClass } from 'react'
import Tab from 'components/Tab.js'
const { number, func } = React.PropTypes
// Alternatively, you can use es6 classes...
export default createClass({
propTypes: {
activeTabIdx: number.isRequired,
activateTab: func.isRequired
},
render () {
const { activeTabIdx } = this.props
const tabs = ['Tab 1', 'Tab 2', 'Tab 3']
return (
<div className='view__tabs'>
<ol className='tabs'>
{this.renderTabLinks(tabs, activeTabIdx)}
</ol>
</div>
)
},
renderTabLinks (tabs, activeTabIdx) {
return tabs.map((tab, idx) => {
return (
<Tab
onClick={this.props.activateTabIdx.bind(this, idx)}
isActive={idx === activeTabIdx}
>
{tab}
</Tab>
)
})
}
})
组件/Tab.js
import React, { createClass } from 'react'
const { func, bool } = React.PropTypes
// Alternatively, you can use es6 classes...
export default createClass({
propTypes: {
children: node.isRequired,
onClick: func.isRequired,
isActive: bool.isRequired
},
handleClick (e) {
const { isActive, onClick } = this.props
e.preventDefault()
if (!isActive) {
onClick()
}
},
render () {
const { children, isActive } = this.props
const tabClass = isActive
? 'tabs__items tabs__items--active'
: 'tabs__items'
return (
<li className={tabClass}>
<a className='tabs__item-link' onClick={this.handleClick}>
{children}
</a>
</li>
)
}
这将主要做正确的事情。请记住,这并不处理/关心选项卡内容,因此,您可能希望以不同的方式构建您的视图。