React组件

React Component组件

React组件有两类: "函数"组件和"类"组件.

重要说明:

  • 在组件中如何使用构造函数constructorsuper.(参考链接)

    • 在constructor中使用this, 必须添加super().
    • 在constructor中使用this.props, 必须添加super(props).
    • 使用场景一: 要在构造函数里初始化组件的state
    • 使用场景二: 要在构造函数中,绑定组件交互事件的this到组件实例上.
  • 组件名首字母必须大写, 且每个组件只能有一个根节点(容器).

eg:

import React, {Component} from 'react'

function Greeting() {
  return <h1>hello world!</h1>
}


class Welcome extends Component{
  render() {
    return <h1>hello, world</h1>
  }
}

// 注意:el不是组件
const el = (
  <div>
    <Greeting />
    <Welcome />
  </div>
);

//use1
ReactDOM.render(
  el,
  document.getElementById('root')
);

//不能省略div标签
function App() {
  return (
    <div>
      <Greeting />
      <Welcome />
    </div>
  )
}

//use2
ReactDOM.render(
	<App />,
    document.getElementById('test')
);

组件间通信

规则: props down, events up. 对于某个组件来说它的props属性是只读的, 只能通过通知其父组件, 由父组件的某个方法执行修改操作.

eg:

class Clock extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: new Date()
    };
  }

  componentDidMount() {
    this.timer = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnMount() {
    clearInterval(this.timer);
  }

  //父组件传递的数据修改时触发
  componentWillReceiveProps(nextProps) {
    if (nextProps.enable) {
      console.log('用户开启了时钟');
    } else {
      console.log('用户停止了时钟');
    }
  }

  //组件的方法
  tick() {
    if (this.props.enable) {
      this.setState({
        date: new Date()
      })
    }
  }

  render() {
    return (
      <div>
        <p>
          <span>now Time: </span>
          {this.state.date.toLocaleTimeString()}
        </p>
      </div>
    )
  }
}
class ToggleButton extends Component {
  handleClick() {
    
    //调用父组件在props中提供的onToggleText方法
    this.props.onToggleText();
  }

  render() {
    return (
      <button onClick={ () => this.handleClick() }>
        {this.props.text}
      </button>
    )
  }
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      clockEnable: true
    };
  }

  //该方法注册后, 由子组件调用, 用于修改时钟的开关状态
  toggleClock() {
    let clockEnable = !this.state.clockEnable;
    this.setState({
      clockEnable: clockEnable
    });
  }

  render() {
    return (
      <div className="App">
          <Clock enable={this.state.clockEnable}></Clock>
          <ToggleButton text={this.state.clockEnable ? '停止时钟' : '开启时钟'} onToggleText={ () => this.toggleClock() }></ToggleButton>
      </div>
    );
  }
}

处理组件的交互事件(鼠标点击事件, 用户触摸事件等)

React组件的定义遵循常规ES6 class, 组件的方法并未自动绑定this到class类的实例中.看下面的例子.

eg1:

class Button1 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      status: true
    };
  }

  //e为点击事件的event对象
  handleClick(e) {

    //默认this指向全局对象而不是该组件的实例对象
    this.setState({
      status: false
    });
  }

  render() {
    return (
      <div>

        //比较<button onClick={ (e) => this.handleClick(e) }>
        <button onClick={ this.handleClick }>
          {this.state.status ? '未点击' : '已点击'}
        </button>
      </div>
    )
  }
}

对两种绑定方式的说明:

未绑定this时

  1. <button onClick={ this.handleClick }>等同于><button onClick={ function() { //do sth.} }>, 匿名函数function内部的this默认指向全局对象, 在浏览器中为window对象.

  2. <button onClick={ (e) => this.handleClick(e) }>因为箭头函数没有自己的this, 内部的this指向外部的this, 也就是组件实例.(也可以理解为函数创建时的this,而不函数调用时的this)

要使用第一种方法, 需要在constructor函数中修改该方法中的this指向.

//...
constructor (props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}
//...

组件的生命周期

React component lifecycle

详情请查看:各生命周期详解.

需要注意的是, 是否使用ES6语法, 书写class组件的方式是不同的(参见React官方文档).

组件作用域

在多个组件组合使用场景下:

在父子组件关系中, 子组件无法直接访问到父组件的变量, 父组件的数据只能通过props传递到子组件.

eg:


function Test(props) {
	return (
    	<h1>my test: { props.aa }</h1>
    )
}

class App extends Component {
	render() {
    	const aa = 'test string';
    	return (
        	<div>
            	This is just a test
                <Test test={aa}>
                
                	//仍属于Test的父组件作用域范围
                	{ aa }
                </Test>
            </div>
        )
    }
}
posted @ 2017-07-13 17:15  君寻不惑  阅读(235)  评论(0编辑  收藏  举报