jsx中, 有很多东西, 是不能用htmltag的属性的.

label 的 for  =>  htmlFor
样式类 class => className

语法:

{code} 被解释为 js 代码
<> 被解释为 html

数组可以直接被渲染:

ReactDOM.render([1,2,3], root)
// 会被直接渲染为 123

如果数组元素是一堆 html 标签, 也能被正常渲染.
react列表渲染: list.map((item, index)=>{ ... })就是基于此原理.
对象不能被渲染 !
key值不要绑定index
绑定html:

// 在render函数 return 之前: let str = "<div>hello,world!</div>"
<div dangerouslySetInnerHTML={{__html: str}} />

从名字就可以看出, 能不用就别用.

函数组件

import React from 'react'

export default function Test(props) {
    const {list} = props
    return (
        <div>
            <ul>
                {
                    list.map((item, index) => {
                        return (
                            <li key={index}>{ item }</li>
                        )
                    })
                }
            </ul>
        </div>
    )
}

函数组件中没有自己的状态, 也称之为无状态组件, 没有自己的this, 只有属性props.
所以函数组件存在的意义仅仅是用来展示数据, 不能进行业务逻辑操作. 也没有生命周期, 可以把它当做是一段html, 只是可以按照规定的去显示一些数据的工具.
这并不是说它没有用, 当我仅仅需要展示数据的时候, 我去写一个有生命周期有状态的组件, 肯定显得小题大做.

类组件

// todolist
import React from 'react'
export default class extends React.Component {
    state = {
        list: [],
        title: ''
    }
    handleChange = (e) => {
        this.setState({
            title: e.target.value
        })
    }
    handleAdd = () => {
        if(this.state.title.trim() === ''){
            alert('task cannot be null!')
            this.setState({
                title: ''
            })
            return;
        }
        this.setState({
            list: [...this.state.list, this.state.title.trim()],
            title: ''
        })
    }
    handleDel = (index) => {
        let list = this.state.list
        list.splice(index, 1)
        this.setState({
            list: list
        })
    }
    render() {
        return (
            <div>
                <div>
                    <input type="text" onChange={this.handleChange} value={this.state.title}/>
                    <button onClick={this.handleAdd}>Add</button>
                </div>
                <ul>
                    {
                        this.state.list.map((item, index) => {
                            return (
                                <li key={index}>
                                    <span>{item}</span>
                                    <button onClick={()=>{this.handleDel(index)}}>delete</button>
                                </li>
                            )
                        })
                    }
                </ul>
            </div>
        )
    }
}

react 的双向数据绑定, 没有vue那么快, 因为react没有双向数据绑定这个机制
需要自己手动实现

<input type="text" onChange={this.handleChange} value={this.state.title}/>
<span>{ this.state.title }</span>

state = {
  title: ''
}
handleChange = (e) => {
  thius.setState({
    title: e.target.value
  })
}

某一次操作重复修改 state

handleClick = () => {
   this.setState({ count: this.state.count + 1 })
   this.setState({ count: this.state.count + 2 })
   this.setState({ count: this.state.count + 3 })
}

这一次执行的结果只是, count 变成了 + 3
react 有一个penddingState, 为了减少操作的次数, 会让这次操作中所有state 全部就位之后, 再去一次性修改组件里的state. 所以分析这次操作的状态就是:

+ 1 => pendingState
+ 2 => pendingState  // 覆盖之前的 + 1
+ 3 => pendingState  // 覆盖之前的 + 2
执行修改state    pendingState => state

如果想得到之前预期的结果 也就是 + 6:

this.setState((prevState) => {
   return {
      count: prevState.count + 1
   }
})
this.setState((prevState) => {
   return {
      count: prevState.count + 2
   }
})
this.setState((prevState) => {
   return {
      count: prevState.count + 3
   }
})