作者:Jogis
原文链接:https://github.com/yesvods/Bl…
转载请注明原文链接以及作者信息
在react生态圈里面,组件的设计非常自由。因为react本身只提供组件渲染以及生命周期,至于用户交互、数据交
互、组件状态之间的关系,并没有强关联。
react组件设计模式分类
long long age,人们对组件模式毫无感知,只知道input
渲染一个输入框,设置value
输入框就有这个值。自组件化盛行,便衍生出另外两种极端的设计模式。
控制组件(controlled component)
顾名思义,就是会被父组件控制的组件,其状态完全决定于父组件。拿我们最熟悉的input
组件来举个栗子。控制组件input
会有一个value
的参数,输入框内容决定于value
,除非它变化了,不然输入框内容不会更改。
class input extends Component {
render(){
return (
<input type="text" value="i won't be change whatever you do" />
)
}
}
这样,无论用户如何输入,输入框内容都可以保持不变,当然我们可以监听用户输入事件来相应改变value
:
class input extends Component {
render(){
return (
<input type="text" value={this.state.v} onChange={e => {
this.setState({v: e.target.value})
}}/>
)
}
}
非控制组件(uncontrolled component)
与控制组件相反,非常自由,不会带有value属性,自我管理状态,通常非控制组件需要一个默认值defaultValue
,自此之后,父组件对非控制组件状态再也无能为力。
class input extends Component {
render(){
return (
<input type="text" defaultValue="i will change to what you input" />
)
}
}
实际应用下,非控制组件用武之地非常少,一般用于状态与外界毫无交互关联时。
w3c组件模式
好了,上面都是废话,想要更详细了解控制、非控制组件,可以参考react官网文章下面才是有用的。
一个正常的input组件
我们平时写HTML用的input组件都很灵活,比如:
<input value="可以当默认状态用啦">
还可以用js来改变状态,当然,就算用js直接改写状态,dom节点的value还是以前的那个。
inputDom.value = "我变了,js先动的手"
inputDom.value // "我变了,js先动的手"
inputDom.getAttribute('value') //"可以当默认状态用啦"
对应的react组件设计模式
我们习惯于灵活地使用一个组件,也就是说,用户输入了,你得变。从网络上拿到数据了,你也要更新自己啊。灵活的组件模式,状态会被外部以及用户改变。
class input extends Component {
constructor(props){
//初始化时候你以为就不用工作了吗,变!
this.state = {v: props.value}
}
componentDidMount(){
this.count = 0;
setInterval(()=> {
//说不定要定时从外面拿点资料更新一下呢
this.setState({v: this.count++});
}, 2000)
}
componentWillReceiveProps(nextProps){
//喏,父组件要你变,你也得改变一下啊
this.setState({v: nextProps.value});
}
render(){
return (
<input type="text" value={this.state.v} onChange={e => {
//你看,用户输入也要改变状态啊,好累
this.setState({v: e.target.value})
}}/>
)
}
}
这组件好强啊,什么场景都可以用。那有什么缺点吗,别跟我说prefect。
好吧,其实,有两个问题:
父组件不能直接读取子组件状态,毕竟控制人家的又不只有你。说不定你读的是上一刻的状态呢。
写起来毕竟费力..嗯,这个也算
在很多场景,需要管理表单的状态,又不能限制组件的状态灵活度,一般会使用第三种设计模式来做表单组件。我们可以通过其他途径直接获得子组件的内部真实状态,通过context或者回调方法,让子组件主动上报自己的状态,父组件对状态做一个汇总。(真实组织信息传递形式周报,好像发现了什么)。
总结
组件设计模式有三种:控制组件,非控制组件,混合控制组件。实际工作中,让所有react表单组件遵循第三种设计模式,可以很清晰设计出灵活通用的组件。并通过状态收集机制(排期到后面的文章),一套健壮的组件就出炉了。