如题~~~

直接上干货!

逻辑与表示 分离

Logic 和 Presentation 分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Pig = ({weight, color, mature}) => (
<div>
<p>weight: {weight}</p>
<p>color: {color}</p>
<p>mature: {mature}</p>
</div>
)
class PigContainer extends React.Components {
constructor(props){
super(props);
this.state = {
weight: 100,
color: 'white',
mature: false,
}
}
render(){
return <Pig {...this.state} />
}
}

好处:单独测试数据与逻辑,如果设计稿要修改,只需要修改相应的显示组件

Mixins

在多个组件间分享同一种功能,mixin只能在React.createClass方法中使用,已经要废弃了,举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const windowResizeMixin {
getInitialState() {
return {
innerWidth: window.innerWidth,
}
},
componentDidMount() {
window.addEventListener('resize', this.handleResize)
},
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
},
handleResize() {
this.setState({
innerWidth: window.innerWidth,
})
}
}
const SomeCopmponent = React.createClass({
mixins: [windowResizeMixin],
render() {
console.log('window.innerWidth', this.state.innerWidth)
...
},
})

可以看到Mixin其实还蛮好用的,但为什么要废气他呢,笔者认为这玩意破坏了组件里面的state的完整性,容易造成复写,另外有些mixin需要实现组件其中的某些方法才能生效,如果mixin多了,我们没有办法很快知道要实现哪些方法,很难管理,所以后来他们想到了更好的解决方案:高级组件

High-order Components

套路是这样的:

1
const HoC = Component => EnhancedComponent

就是把组件作为参数传入函数,然后返回一个加强功能版的组件,就像把Steven放进锅炉炖一下就变成了美国队长~~~
把上面Mixin写成HoC后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const withInnerWidth = Component => (
class extends React.Component {
constructor(props){
super(props);
this.state = {
innerWidth: window.innerWidth
}
this.handleResize = this.handleResize.bind(this);
}
componentDidMount() {
window.addEventListener('resize', this.handleResize)
},
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
},
handleResize() {
this.setState({
innerWidth: window.innerWidth,
})
}
render(){
return <Component {...this.props} {...this.state} />
}
}
)
const SomeCopmponent = ({ innerWidth }) => {
console.log('window.innerWidth', this.state.innerWidth);
...
}
const SomeCopmponentWithInnerWidth = withInnerWidth(SomeCopmponent); // toasted!

不要被这个栗子束缚了,所有的HoC都是函数,而且可以动态配置里面的传参,那么函数是可以嵌套的,有一个库Recompose用来处理嵌套的问题

Context

这里不得不提一下Context,这个属性虽然快要被废弃了,但是配上HoC,功能非常强大,可以在所有使用过该HoC的组件间共享状态。具体可以看react-redux是怎么实现的。

Function as Child!

套路是这样的:

1
2
3
4
const FunctionAsChild = ({ children }) => children()
FunctionAsChild.propTypes = {
children: React.PropTypes.func.isRequired,
}

那么这玩意能干嘛呢,举个栗子吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Fetch extends React.Component {
constructor(props){
super(props);
this.state = {
data: [];
}
}
componentDidMount() {
ajax().then((res) => {this.setState({data: res})})
}
render() {
return this.props.childen(this.state.data);
}
}
<Fetch url="...">
{data => <List data={data} />}
</Fetch>

这个和HoC有什么区别呢?这个能动态绑定参数啊,url也许是动态变化的呢,HoC就懵逼了对不对=。=

好了,套路介绍到这里~