Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

组件设计模式 #9

Open
yesvods opened this issue Sep 26, 2016 · 0 comments
Open

组件设计模式 #9

yesvods opened this issue Sep 26, 2016 · 0 comments

Comments

@yesvods
Copy link
Owner

yesvods commented Sep 26, 2016

组件设计模式

在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表单组件遵循第三种设计模式,可以很清晰设计出灵活通用的组件。并通过状态收集机制(排期到后面的文章),一套健壮的组件就出炉了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant