es6语法的reactjs的state状况和组件间props通报的实践

PS:开首的一段空话

       想起一个月前还不晓得reactjs该怎样动手的如今天有点小体味,照样有点小欣喜,不过回望一些走过的坑和开始时的满头浆糊以为照样有点恐惧的。本日分享一点实践中的小心得给新手朋友们。

reactjs的es6语法情势

       其他的就没必要多说,只说说两个点:

  • constructor和super

  • this.functionName=this.functionName.bind(this)

       constructor(props)和super(props)平常是要么不涌现,要么同时涌现,意义现实上就是继续,这两个东西实在并非reactjs的,而是es6的,前者就是一个平常意义的组织函数,相当于es5内里的

function FunctionName(props) {
    this.props=props;
}

       super(props)则是继续父类的属性,(意义相当于es5中的 function Son(name){ Parent.call(this, name) }),并在constructor内部准确拿到this,这个this指向此时的子类。假如在操纵this之前(比方console.log(this))没有写super(props)则会报错,意义大概是:不能在super()之前写this!

       而有时刻看到constructor()和super(),即没有写props彷佛也没有什么问题,缘由自然是没有在constructor内部用到this.props,现实上在constructor内部平常用到的是this.state占多数,貌似this.props没怎么写。。。

       this.functionName=this.functionName.bind(this)这个是绑定要领到子类上,使得这个this就是当前的子类(所谓的this指向)。还能够直接将.bind(this)写函数定义的处所,比方在render衬着的元素上 onClick={this.handleClick.bind(this)}.

this.state和this.setState({})以及propsName={stateName}

       state在reactjs组件状况衬着内里的作用显而易见,被称为状况衬着机,元素节点的种种属性值及其转变现实上基本是由state供应的状况值及其转变完成的。比方元素的文本转变、表单的value值、checked、disabled以至css款式都能够做到用state来衬着。以下供应一个简例辅佐申明:

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
class Comp extends React.Component {
    constructor(){
        super();
        this.handleChange=this.handleChange.bind(this);
        this.handleClick=this.handleClick.bind(this);
        this.state={
            value: "",
            msg: ""
        }
    }
    handleChange(e){
        this.setState({
            value: e.target.value
        })
    }
    handleClick(){
        let {value}=this.state;
        $.ajax({
            ...
            data: {
                value:value
            },
            success:(data)=>{
                this.setState({
                    msg: data
                })
            }
        })
    }
    render(){
        let {value,msg}=this.state; 
        return(
            <div>
                <input type="text" value={value} onChange={this.handleChange} />
                <input type="button" value="提交" onClick={this.handleClick} />
                <span>{msg? msg:"此处加载ajax返回的信息"}</span>
            </div>
        )
    }
}
ReactDOM.render( <Comp />, document.body)

       以上简例在页面上衬着以后是一个按钮、一个输入框和一个信息提醒。由于reactjs首倡单向数据流,在value状况初始为空的状况下,假如直接在输入框中输入而不设置value状况(setState),输入信息没法猎取。这个衬着历程是:起首页面加载时依据默许的this.state中的三个状况值天生响应的状况,onChange事宜不停转变state的value值,此时state吸收到了转变并立时从新衬着页面上输入框内的值,即:只需任何行动转变了state值,页面就会从新衬着响应的处所(关于其他reactjs入门案例demo能够拜见本人的github)。

props属性以及通报

       注重一下,以上说constructor内假如没有通报props参数,其内部就不能运用this.props。但这并不意味着其他处所比方render内部不能运用。如今只是体味到组件之间通报的props值的初始泉源平常都是state值,多是实践不够的缘由 @_@。。。

1.父组件向子组件传值

       这是比较罕见的父子组件之间通讯的体式格局。子组件上的属性值能够理解为一个参数,而须要父组件通报一个现实值。传值这类体式格局平常是复用组件所必需的,由于有可能有多个页面的内容的某一个部份高度相似以至雷同,这时候只须要对一个组件通报差别的值就能够完成屡次运用。以下例:

假定组件文件都在根目录下:
//子组件Son.js
class Son extends React.Component{
    render(){
        let {title,userValue,pwdValue,handleChange,handleSubmit}=this.props;
        return(
            <div>
                <h3>{title}</h3>
                <input type="text" value={userValue} onChange={(e)=>handleChange("user",e.target.value} />
                <input type="password" value={pwdValue} onChange={(e)=>handleChange("pwd",e.target.value} />
                <input type="button" value="提交" onClick={handleSubmit} />
            </div>
        )
    }
}
//父组件1:Login.js
import Son from './Son.js';
class Login extends React.Component{
    constructor(){
        super();
        this.handleChange=this.handleChange.bind(this);
        this.handleSubmit=this.handleSubmit.bind(this);
        this.state={
            user:{
                value:"",
                error:false
            },
            pwd:{
                value:"",
                error:false
            }
        }
    }
    handleChange(field,val){
        let newState={value:val, error:true};
        switch(field) {
            case "user":
                if (!val.length){
                    newState.error=false
                } else if (val.length>4) {
                    newState.error=false
                }
                this.setState({
                    user:newState
                })
                break;
            case "pwd":
                if (!val.length){
                    newState.error=false;
                } else if (val.length>6) {
                    newState.error=false
                }
                this.setState({
                    pwd:newState
                })
                break;
        }
    }
    handleSubmit() {
        let {user, pwd}=this.state;
        if (!user.error || !pwd.error) {
            alert("请重试!");
            return;
        } else {
            $.ajax({
                ...
                data: {
                    username: user.value,
                    password: pwd.value
                },
                ...
            })
        }
    render(){
        let {user, pwd}=this.state;
        return(
            <Son title="请登录" userValue={user.value} pwdValue={pwd.value} handleChange={this.handleChange} handleSubmit={this.handleSubmit} />
        )
    }
}

       置信列位看得出来,这是个登录页面的雏形,个中仅限原理申明,先不要纠结范例什么的哈。。。平常来说,既然有登录,也就有注册,注册页面基本上也是这个原理。须要申明的是:子组件上的属性值和要领都是this.props的,这里之所以没有写this.handleChange或许this.handleSubmit是由于子组件自身没有这个要领,因而假如此时在子组件上的要领前加上this.xxx就会报错大概说这个要领不是个函数!属性值也相似;同时运用拆包表达式写this.props示意这些属性和要领都是从父组件上继续而来,只需父组件上定义了要领,因而子组件上此时能够不必写constructor()和super()。

2.父组件的父组件子组件传值

       这个场景重要用于组件嵌套比较多的时刻。比方,我们发如今子组件Son.js中,有三个输入框分别是用户名、暗码,但貌似有点不三不四,那末我们就完美一点这个表单:

新建组件Form.js
class Form extends React.Component{
    render(){
        let {handleSubmit, userValue, pwdValue, handleChange}=this.props;
        return(
            <form  onSubmit={handleSubmit} method="post" action="/submit">
                <input type="text" name="user" value={userValue} onChange={(e)=>handleChange("user",e.target.value} />
                <input type="password" name="pwd" value={pwdValue} onChange={(e)=>handleChange("pwd",e.target.value} />
                <input type="submit" />
            </form>
        )
    }
}

       有了这个组件以后,关于表单的Son.js组件能够改形成(一样假定一切组件都在根目录下):

//Son.js
import Form from  './Form.js';
class Son extends React.Component{
    render(){
        let {title,userValue,pwdValue,handleChange,handleSubmit}=this.props;
        return(
            <div>
                <h3>{title}</h3>
                <Form 
                    userValue={userValue}
                    pwdValue={pwdValue}
                    handleChange={handleChange}
                    handleSubmit={handleSubmit}
                />
            </div>
        )
    }
}

       或许新手童鞋们不太邃晓Son.js组件上的属性和要领定名究竟是不是是一定要和孙子级组件上的一样,由于本人在学这个处所的时刻确实纠结过,不过请注重:只需onChange或许onSubmit这类元素上原生要领后指定的一个函数(Form.js),比方onChange={handleChange},那末这个handleChange在通报的时刻,上级组件(Son.js)上的handleChange={handleChange}中,左侧是上级组件的要领,能够新定名比方footChange。。。而右侧则是通报给下级组件的要领handleChange,所以,下级组件Form.js中onChange的右侧函数名必需对应之。

       另外,我们还能够依据Son.js做个简朴的迎接页:

//Welcome.js
class Welcome extends React.Component{
    render(){
        return(
            <h1>迎接您!</h1>
        )
    }
}
//SonWelcome.js
import Welcome from './Welcome.js';
class SonWelcome extends React.Component{
    render(){
        return(
            <div>
                <h3>{this.props.title}</h3>
                <Welcome />
            </div>
        )
    }
}

       固然,SonWelcom.js太甚简朴了。。。同时title的值依赖于上一级组件传值一定,兄弟们大开脑洞吧。

3.非上下级关联和非兄弟的组件之间怎样传值

       置信这个状况是比较少的,不过这是个值得研讨的,有一些师兄和大神们一定晓得怎样处理。所谓的兄弟组件就是具有配合的父组件或许“爷组件”的多个组件,这类状况和以上差不多,重要把兄弟组件之间须要的配合的值挂载到上级组件即可。而非上下级和非兄弟组件这类状况的运用场景有点相似(注重,仅仅是相似)session或许cookie,比方有多个页面须要依据用户是不是登录或许是不是是管理员超等用户来对页面举行差别的衬着。
       先说说能够处理的门路吧,起首引荐的是一个js库:PubSubJs,概况能够去相识一下(现实我也没用过。。。)。其次,说说本人的主意吧。正如上所言,假定这个属性或许要领在衬着组件的时刻并不触及平安性问题,那末何不将其设置为cookie或许session呢?哪一个组件须要这个值就将其提出来。以下例两个组件:
临时写以下,先不论自定义flag从何而来,同时,.active的款式是:display:none;

//CompOne.js
class CompOne extends React.Component{
    render(){
        return(
            <div>
                <p className={flag? "":"active"}>这个第一个组件</p>
            </div>
        )
    }
}
//CompTwo.js
class CompTwo extends React.Component{
    render(){
        return(
            <div>
                <p className={flag? "active":""}>这个第二个组件</p>
            </div>
        )
    }
}

       假定以上两个组件并没有关联,且都带有一个配合的自定义属性flag,这两个组件依据flag的意义举行隐蔽或展现。此时,能够建一个组件Cookie内部封装一个组织函数HandleCookie,内部封装三个要领setCookie(name, value, time),getCookie(name),clearCookie(name, value, time)。假定,name是cookie称号,value是cookie的值,time参数是参照当前时候的cookie的保留时候长度,设置为1示意一天后逾期,设置-1则示意逾期失效。

       照此假定,以上两个组件能够直接在衬着页面的时刻取到cookie的flag称号对应的值,并依据值衬着页面。比方在项目的某个文件加载终了(componentDidMount)的时刻设置一个cookie:{flag:”1″},CompOne.js:

//CompOne.js
import Cookie from './Cookie.js';
class CompOne extends React.Component{
    render(){
        let flag=Cookie.getCookie("flag");
        return(
            <div>
                <p className={flag? "":"active"}>这个第一个组件</p>
            </div>
        )
    }
}

       照此部署,这个组件CompOne衬着后就会展现,而CompTwo则会隐蔽。不过,这类体式格局显著不是一种范例的要领,仅仅是主意罢了,望轻喷!

写在末端的话

       以上如有不当之处,还请斧正一下,给小弟一个洗心革面的时机吧。。。假如童鞋还对其他没有写完全的处所感兴趣,能够拜见本人的一个留言本小项目,乃是本国reactjs、webpack设置、nodejs和express入门的最好材料之一,以为好用就star一下吧,哎,求star真不好意义^_^

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