资讯专栏INFORMATION COLUMN

es6语法的reactjs的state状态和组件间props传递的实践

malakashi / 587人阅读

摘要:目前只是体会到组件之间传递的值的初始来源一般都是值,可能是实践不够的原因。。。此时,可以建一个组件内部封装一个构造函数,内部封装三个方法。

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(
            
{msg? msg:"此处加载ajax返回的信息"}
) } } ReactDOM.render( , 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(
            

{title}

handleChange("user",e.target.value} /> handleChange("pwd",e.target.value} />
) } }
//父组件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(
            
        )
    }
}

       相信各位看得出来,这是个登录页面的雏形,其中仅限原理说明,先不要纠结规范什么的哈。。。一般来说,既然有登录,也就有注册,注册页面基本上也是这个道理。需要说明的是:子组件上的属性值和方法都是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(
            
handleChange("user",e.target.value} /> handleChange("pwd",e.target.value} />
) } }

       有了这个组件之后,关于表单的Son.js组件可以改造成(同样假定所有组件都在根目录下):

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

{title}

) } }

       也许新手童鞋们不太明白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(
            

欢迎您!

) } }
//SonWelcome.js
import Welcome from "./Welcome.js";
class SonWelcome extends React.Component{
    render(){
        return(
            

{this.props.title}

) } }

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

3.非上下级关系和非兄弟的组件之间如何传值

       相信这个情况是比较少的,不过这是个值得研究的,有一些师兄和大神们肯定知道如何解决。所谓的兄弟组件就是具有共同的父组件或者“爷组件”的多个组件,这种情况和以上差不多,主要把兄弟组件之间需要的共同的值挂载到上级组件即可。而非上下级和非兄弟组件这种情况的应用场景有点类似(注意,仅仅是类似)session或者cookie,比如有多个页面需要根据用户是否登录或者是否是管理员超级用户来对页面进行不同的渲染。
       先说说可以解决的途径吧,首先推荐的是一个js库:PubSubJs,详情可以去了解一下(实际我也没用过。。。)。其次,说说本人的想法吧。正如上所言,假设这个属性或者方法在渲染组件的时候并不涉及安全性问题,那么何不将其设置为cookie或者session呢?哪个组件需要这个值就将其提出来。如下例两个组件:
暂且写如下,先不管自定义flag从何而来,同时,.active的样式是:display:none;

//CompOne.js
class CompOne extends React.Component{
    render(){
        return(
            

这个第一个组件

) } }
//CompTwo.js
class CompTwo extends React.Component{
    render(){
        return(
            

这个第二个组件

) } }

       假设以上两个组件并没有关系,且都带有一个共同的自定义属性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(
            

这个第一个组件

) } }

       照此安排,这个组件CompOne渲染后就会展示,而CompTwo则会隐藏。不过,这种方式明显不是一种规范的方法,仅仅是想法而已,望轻喷!

写在结尾的话

       以上若有不当之处,还请指正一下,给小弟一个改过自新的机会吧。。。如果童鞋还对其他没有写彻底的地方感兴趣,可以参见本人的一个留言本小项目,乃是本国reactjs、webpack配置、nodejs和express入门的最好材料之一,觉得好用就star一下吧,哎,求star真不好意思^_^

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83485.html

相关文章

  • [React Native Android 安利系列]ReactNative中reactjs基础

    摘要:个人感觉这与中的布局文件类似。其中的会被解析。中的标签,由基础库提供。认为,我们的程序是一个状态机。支持我们更改状态,从而引起视图的变化。绑定事件是放在中的。事件名称直接写为标签的属性,其值则是对应的事件处理函数。 这一系列课程说了很多关于react-native的知识,都是有关于样式,底层,环境等知识的,现在我们来学习一下reactjs的基础知识。我们的代码,我们创建的组件的相关知识...

    EddieChan 评论0 收藏0
  • React 深入系列3:Props State

    摘要:当真正执行状态修改时,依赖的并不能保证是最新的,因为会把多次的修改合并成一次,这时,还是等于这几次修改发生前的。下篇预告深入系列组件的生命周期新书推荐进阶之路作者徐超毕业于浙江大学,硕士,资深前端工程师,长期就职于能源物联网公司远景智能。 文:徐超,《React进阶之路》作者授权发布,转载请注明作者及出处 React 深入系列3:Props 和 State React 深入系列,深...

    endiat 评论0 收藏0
  • React 深入系列3:Props State

    摘要:深入系列,深入讲解了中的重点概念特性和模式等,旨在帮助大家加深对的理解,以及在项目中更加灵活地使用。下篇预告深入系列组件的生命周期我的新书进阶之路已上市,请大家多多支持链接京东当当 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深对React的理解,以及在项目中更加灵活地使用React。 React 的核心思想是组件化的思想,而React 组件的定...

    hiyayiji 评论0 收藏0
  • Reactjs vs. Vuejs

    摘要:上图是二月份前端框架排名,位居第一,排名第三。我们认为前端模板和组件代码是紧密相连的。直到最近看了文档,才发现另有蹊跷。 欢迎大家关注腾讯云技术社区-segmentfault官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 纪俊,从事Web前端开发工作,2016年加入腾讯OMG广告平台产品部,喜欢研究前端技术框架。 这里要讨论的话题,不是前端框架哪家强,因为在 Vue 官网就已经...

    AaronYuan 评论0 收藏0
  • React 入门实践

    摘要:更多相关介绍请看这特点仅仅只是虚拟最大限度减少与的交互类似于使用操作单向数据流很大程度减少了重复代码的使用组件化可组合一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。在使用后,就变得很容易维护,而且数据流非常清晰,容易解决遇到的。 欢迎移步我的博客阅读:《React 入门实践》 在写这篇文章之前,我已经接触 React 有大半年了。在初步学习 React 之后就正式应用到项...

    shenhualong 评论0 收藏0

发表评论

0条评论

malakashi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<