React组件Component

在React,组件(component),就是一个UI的单元。它的思想是,将要展示的内容,分成多个独立部分,每一个这样的部分,就是一个组件,就有点像android或者ios中的控件。

组件的基本组成部分

每个组件,其实在代码中提现出来就是一个类,一个最简单的组件:

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

从上面的代码可以看到,组件和一般的类一样可以定义方法。对于组件来说,render()方法是非常重要的(必须实现),就是在这个方法返回组件的界面。在render()方法中,使用了JSX来定义组件的界面。关于render()方法,后面会进一步详述。

此外,组件还有两个重要的东西,一个是属性(props),一个是状态(state)。简单的说,组件的属性是父组件给它的(组件之间可以嵌套),存储的是父组件对子组件的要求,在组件内部可以对属性进行访问(使用),但不可以修改它;组件的状态,由组件自行定义和使用,用来存储组件当前状态,组件的状态可以修改。

组件的生命周期

组件的生命周期大体上可以分为三个阶段:展示(mounting),刷新(updating),消失(unmounting)。
在每个阶段中,又细分了几个步骤。

1. 展示阶段(Mounting)

就是组件被创建并插入视图的阶段,以下方法依次执行:

  • constructor(props)

组件创建的时候会被调用,在该方法内可以访问到由父组件传来的属性对象props。如果要重写这个方法,必须记得先写super(props);否则在这个组件内部就访问不了属性了(属性的内容稍后详述)。

  • componentWillMount()
  • render()
  • componentDidMount()

2. 刷新阶段(Updating)

当组件的属性(props)和状态(state)改变的时候会触发组件进行刷新,以下方法一次执行:

  • componentWillReceiveProps(nextProps)

组件的属性变化的时候会调用,这个方法中nextProps就是新的属性。如果想在该方法内更新状态,应该先确保属性当前值和新值不相同后再刷新状态。

  • shouldComponentUpdate()

这个方法返回true或者false决定组件的render()方法是否会被调用。

  • componentWillUpdate()
  • render()
  • componentDidUpdate()

3. 消失阶段(Unmounting)

组件被移除之后就会进入消失阶段,执行以下方法:

  • componentWillUnmount()

组件的属性、状态和方法

在组件的内部,要访问自身的属性、状态和方法,一般需要使用到this关键字,表示本组件的意思。

1. 组件的方法

访问组件的方法使用格式:
this.methodName(param1,param2,…)
如,在组件内部定义了方法:

_method()
{
console.log(‘method call ! ~~~~’);
}

要调用它:
this._method();

2. 组件的属性

上面提到,组件的属性,是由父组件给的,从意义上理解,组件的属性用来存储父组件对子组件的要求。
访问组件的属性格式:
this.props.propertyName
这里看到,与访问组件的方法不同,这里没有直接在this后就直接跟属性名,中间多了一个props。这个props其实是一个属性对象,上面我们提到属性是父组件给的,那么这个props对象就相当于把父组件给的所有的属性都封装起来,一个props对象像这样:

{
property1:value1,
property2:value2,
…
}

注意,在使用react的时候会经常遇到用这种形式表示的对象,也就是一个花括号内包含若干对属性名和属性值。
访问组件的属性的例子:
例如组件有一个属性height,那么要访问它:
this.props.height;
虽然属性不能修改,但我们能给组件属性一个默认值,也就是说,当父组件没有给该属性赋值的时候,使用的一个默认值。
例如给组件CustomButton定义默认属性:

CustomButton.defaultProps = {
  color: 'blue'
};

另外还可以给组件的属性指定类型,在开发模式下这个如果父组件设置的属性不符合子组件设定的类型的话,会输出警告,在生产模式下就不会对类型进行检查,例如,设定CustomButton组件的color属性的类型为字符:

CustomButton.propTypes = {
  color: React.PropTypes.string
};

3. 组件的状态

组件的状态,就是用来存储组件的当前状态。
访问状态的格式:
this.state.propertyName
例如,组件有个属性height,那么要访问它对应的状态:
this.state.height;
与组件的属性类似,这里也没有直接在this后跟属性名,中间多了个state。类似的,state也是一个状态对象,把所有属性对应的状态封装起来。既然是对象,当然也可以使用上面说的“花括号内包含若干对属性名和属性值”的形式来表示,像这样:

{
property1:value1,
property2:value2,
…
}

上面提到,属性是父组件给的,不可修改,但状态可以修改。由于状态是一个对象,因此修改状态,就是给this.state赋予一个新的对象:

this.state = {
propertyName1:newValue1,
propertyName2:newValue2,
…
};

或者使用setState()方法,这个方法会将新的、旧的状态合并,因此只需要填入有变化的状态就好,

this.setState({
propertyName1:newValue1,
propertyName2:newValue2,
…
});

例如,修改一个组件的两个状态height和width分别为100和200:

this.state = {
height:100,
width:200,
};

this.setState({
height:100,
width:200,
});

组件的render()方法

上面提到,render()方法是专门用来返回组件界面的。从组件的生命周期可以看出,在组件第一次加载的时候,或者组件的props或state有变化的时候,render()方法都会被调用,也就是说这两种情况下,组件会重画它的界面,因此在render()方法中尽量只做有关界面的事情。
组件的界面也是由一个或多个其他的组件组成的,比如View、Button、Text等等。需要注意的是,如果当多个子组件都需要使用同一个状态(状态可能会改变)的时候,为了减少对状态(属性)的访问次数,建议在render()方法中,先用一个变量存储该状态的当前值,然后在各个组件中使用这个变量,而不是在各个组件中多次访问这个状态。
例如,这里组件Text、Input、Image都是用到了this.state.value,推荐的写法是:

 render() {
    const value = this.state.value;
    return (
    <View>
      <Text>{value}</Text>
      <Input value={value} onChange={this.handleChange} />
      <Image source = {{ uri : value }}/>
    </View>
    );
  }

在上面的例子当中,return()方法内部是由的是JSX,ReactNative支持的表示界面的一种语法,类似于XML或者HTML。这个可以去查查看。
这个例子里,组件使用的都是this.state.value。这里可能就存在疑惑,在组件中什么时候应该用props,什么时候应该用state。下面看,属性和状态的使用场景。

属性和状态的使用场景

在组件中应该用props还是state,取决于这个信息是来自于组件内部还是来自于组件外部。什么意思呢?
例如,自定义一个组件CustomView(如下图)。CustomView包括一个输入框组件Input和一个文本框组件CustomText。现在要求CustomText显示的文本随Input中输入的内容变化(输入什么就显示什么)。
这里写图片描述
对于组件CustomView,其子组件CustomText的要显示的文本来自于子组件Input,都是在CustomView的内部,因此CustomView可以用this.state.value来存储输入框的内容,然后CustomText就显示this.state.value。
那么站在组件CustomText的角度,假定CustomText内部包含一个Text组件,实际上文本是由Text组件显示的(如下图):
这里写图片描述
为了满足组件CustomText的文本随输入框的内容改变,就要求CustomView要将输入框的内容传到CustomText内部,这样CustomText的子组件Text才可以访问到。这就需要用到属性。如果CustomView通过属性textFromInput传给CustomText的话,在CustomText内部,就可以通过this.props.textFromInput访问到。
所以CustomView的render()方法应该是这样的:

render(){
     var value = this.state.value;
     return(
        <CustomText textFromInput = {value}/>
        <Input onChange = {this._inputValueChange}/>
     );
}

CustomText的render()方法应该是这样的:

render(){
     return(
        <Text>{this.props.textFromInput}</Text>
     );
}

这时候,只要实现每次输入内容变化的时候更新状态value,就可以实现CustomText的内随输入内容变化。上面onChange指向_inputValueChange方法,于是实现该方法:

this._inputValueChange(e){
    this.setState({
    value:e.target.value;
    });
}
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值