组件设计模式

作者:Jogis
原文链接:https://github.com/yesvods/Bl…
转载请注明原文链接以及作者信息

在react生态圈里面,组件的设计非常自由。因为react本身只提供组件渲染以及生命周期,至于用户交互、数据交
互、组件状态之间的关系,并没有强关联。

react组件设计模式分类

long long age,人们对组件模式毫无感知,只知道input渲染一个输入框,设置value输入框就有这个值。自组件化盛行,便衍生出另外两种极端的设计模式。

控制组件(controlled component)

顾名思义,就是会被父组件控制的组件,其状态完全决定于父组件。拿我们最熟悉的input组件来举个栗子。控制组件input会有一个value的参数,输入框内容决定于value,除非它变化了,不然输入框内容不会更改。

controlled component 1

class input extends Component {
    render(){
        return (
            <input type="text" value="i won't be change whatever you do" />
        )
    }
}

这样,无论用户如何输入,输入框内容都可以保持不变,当然我们可以监听用户输入事件来相应改变value

controlled component 2

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,自此之后,父组件对非控制组件状态再也无能为力。

uncontrolled component

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组件设计模式

我们习惯于灵活地使用一个组件,也就是说,用户输入了,你得变。从网络上拿到数据了,你也要更新自己啊。灵活的组件模式,状态会被外部以及用户改变。

mixed model component

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。

好吧,其实,有两个问题:

  1. 父组件不能直接读取子组件状态,毕竟控制人家的又不只有你。说不定你读的是上一刻的状态呢。

  2. 写起来毕竟费力..嗯,这个也算

    在很多场景,需要管理表单的状态,又不能限制组件的状态灵活度,一般会使用第三种设计模式来做表单组件。我们可以通过其他途径直接获得子组件的内部真实状态,通过context或者回调方法,让子组件主动上报自己的状态,父组件对状态做一个汇总。(真实组织信息传递形式周报,好像发现了什么)。

总结

组件设计模式有三种:控制组件,非控制组件,混合控制组件。实际工作中,让所有react表单组件遵循第三种设计模式,可以很清晰设计出灵活通用的组件。并通过状态收集机制(排期到后面的文章),一套健壮的组件就出炉了。

    原文作者:Jogis
    原文地址: https://segmentfault.com/a/1190000007015934
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞