React元素&组件

元素

React元素是普通的对象,其与浏览的的DOM元素不同,而React DOM的作用是确保浏览器的数据内容与React元素保持一致

通常我们设置一个 id为root的div 将其内容都由React DOM来管理,就称之为根节点

元素渲染

React元素是不可变的,当被创建后无法改变其内容和属性,我们可以通过设置不同的react元素挂载到根节点来更新界面

function tick() {
    const element = (
        <div>
            <h1> hello lyy!</h1>
            <h2> It is {new Date().toLocaleTimeString()}</h2>
        </div>
    )
    ReactDOM.render(element, document.getElementById('root'))
}

setInterval(() => {
    tick()
}, 1000);

但是我们通常在项目中只挂载一次,因此我们想要更新元素,就需要使用到有状态组件

ReactDOM为了节约性能 会比较前后元素的不同后,只会渲染改变的部分,因此对于上面的例子 即使每秒钟都创建了新的元素 也只会渲染改变的部分而不是整个页面

组件

组件是一个或者多个React元素的组合,接受任意的输入值(props)在页面上进行展示

定义组件方法:

{name: "liyuyuan"}作为props传给新的组件

//使用函数
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}

//使用class
class Welcome extends React.Component {
  render() {
    return <h1>Hello, svg, {this.props.name}</h1>
  }
    
    //设置挂载点为 Welcome 组件 
  ReactDOM.render(<Welcome name="liyuyuan"/>, document.getElementById('root'));

}

组件也可以作为React元素

  const element = <Welcome name="zhe shi shen me?" />

组件返回只能为一个根元素,因此需要把这几个元素用div进行包裹

function WelcomeTest(props) {
  return (
    <div>
        <Welcome name="zhe 第一行?" />
        <Welcome name="zhe 第二行" />
        <Welcome name="zhe 第三行" />

    </div>
  )
}

Props属性是只读的

组件不能修改自己的props,意思是不能改变自己的输入值,当输入值相同时一定得到相同的输出结果(纯函数)

条件渲染

可以根据条件渲染不同的组件

render() {
    let element
    if(true) {
        element = <a href="#" onClick={this.actionClick}> Click Me </a>
    } else {
        element = <a href="http://www.baidu.com" onClick={this.actionClick}> Click Me </a>
    }
    return element
    
}

在jsx代码中嵌入逻辑js代码和React元素 条件渲染元素

render() {
    return(
        <div>
            {true && <h1> 条件渲染 </h1>}
        </div>
    )
}

条件性不渲染元素

    render() {
        if (true) {
            return null
        } else {
            return (
                <h1>条件渲染</h1>
            )
        }
        
    }

当不渲染元素时 可以返回null
当返回null时 并不影响组件的声明周期函数

列表组件

利用js中的map函数 创建一个元素列表组件

function NumberList(props) {
    const numbers = props.numbers;
    const listItems = numbers.map((number) =>
    //创建一个元素,需要加一个特殊的key值
      <li key={number.toString()}>{number}</li>
    );
    return (
      <ul>{listItems}</ul>
    );
}

元素的key

我们在创建列表元素时, 当该元素有多个兄弟元素时,需要给元素增加标识即 key ,帮助在DOM中元素发生变化后识别哪些元素发生了变化.元素的key应该在兄弟元素间是唯一的(并不需要全局唯一,即多个非兄弟关系的元素之间key可以相同) 通常使用数据id(如果没有id就用下标index)作为元素的key

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

//在jsx代码中嵌入js表达式
function NumberList(props) {
    const numbers = props.numbers;

    return (<ul>
        { numbers.map((num) => (<li key={num}>
            {2*num}
        </li>)) }
    </ul>)
}

表单

受控组件

受控组件:即将组件的每个状态改变都有与之相关的处理函数,控制其行为

Form

我们将表单改变为一个可控的组件 将值的改变包括在组件的state中,通过state改变组件的渲染
改变submit时会自动刷新页面的行为即阻止默认行为

export default class FormElement extends React.Component {

    constructor(props) {
        super(props)
        this.state = {value: ''};

        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }

    handleChange(event) {
        this.setState({value: event.target.value})
    }
    
    handleSubmit(event) {
        //阻止提交表单的默认行为
        event.preventDefault();
    }

    render() {
        return(
            <form  onSubmit={this.handleSubmit}>
                <label>
                    Name:
                    <input type="text" value={this.state.value} onChange={this.handleChange}></input>
                </label>
                <input type="submit" value="Submit"></input>
            </form>
        )
    }
    
}

event.preventDefault(); 阻止默认行为

当一个控件中存在多个受控元素,我们可以给元素指定name属性,让处理函数根据event.target.name值来选择做什么

constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
    //利用计算属性名 来设置状态值的键
      [name]: value
    });
  }