组件分类

函数组件

  1. function Welcome(props) {
  2. return <h1>Hello,{props.name}</h1>
  3. }
  4. // 使用
  5. <Welcome name="frank"/>

类组件

  1. class Welcome extends React.Component {
  2. render() {
  3. return <h1>Hello,{this.props.name}</h1>
  4. }
  5. }
  6. // 使用
  7. <Welcome name="Frank" />

<Welcome /> 会变成一个react 语法,而不是变成HTML元素

  1. <div />会被翻译为React.createElement('div')
  1. <Welcome />翻译为React.createElement(Welcome)

props(外部数据)

外部数据不能写 只能读取

类子组件

this.props.xxx

  1. // 父组件
  2. function App() {
  3. return (
  4. <div className="App">
  5. 爸爸
  6. <Son messageForSon="我是你爸爸" /> // “123”字符串或者JS表达式{a+b}
  7. </div>
  8. )
  9. }
  10. // 类子组件
  11. class Son extends React.Component {
  12. render() {
  13. return (
  14. <div className="Son">
  15. {this.props.messageForSon}
  16. </div>
  17. )
  18. }
  19. }

函数子组件

props.xxx

  1. // 父组件
  2. class Son extends React.Component {
  3. render() {
  4. return (
  5. <div className="Son">
  6. {this.props.messageForSon}
  7. <Grandson messageForGrandSon="训责你" />
  8. </div>
  9. )
  10. }
  11. }
  12. // 子组件
  13. const Grandson = (props) => {
  14. return (
  15. <div className="Grandson">
  16. {props.messageForGrandSon}
  17. </div>
  18. )
  19. }

state(内部数据)

类组件

  1. // 声明
  2. constructor() {
  3. super()
  4. this.state = {
  5. n: 0
  6. }
  7. }
  8. // 调用
  9. n: {this.state.n}
  10. // 更新
  11. <buttononClick={() => {this.add()}}>
  12. +14
  13. </button>
  14. add() {
  15. // 写法一
  16. // this.setState({ n: this.state.n + 1 }) // 重新声明一个对象
  17. // 写法二
  18. // 这里的n 不会立刻变 会等一会儿改变
  19. this.setState(state => {
  20. const n = state.n + 1
  21. return { n }
  22. })
  23. }

setState(函数) 最好用这个方式 方法一里面的n 不会同步更新。

函数组件

  1. // n 是读的值 setN 是写的值
  2. const [n, setN] = React.useState(0)
  3. // 读取
  4. n:{n}
  5. // 写
  6. setN(n + 1) // 永远不会改变n 会产生一个新的n

类组件注意事项

this. state.n += 1无效?

其实n已经改变了,只不过UI不会自动更新而已

调用setState才会触发UI更新(异步更新)

因为React没有像Vue监听data一样监听state

setState会异步更新UI

setState之后,state 不会马上改变,立马读state会失败(读取的是旧的)

更推荐的方式是setState(函数)

this. setState(this. state)不推荐?

React希望我们不要修改旧state (不可变数据)

常用代码: setState({n: state.n+1})

函数组件注意事项

跟类组件类似的地方

也要通过setX(新值)来更新UI

跟类组件不同的地方

没有this, 一律用参数和变量

引用多个值

类组件

  1. class Son extends React.Component {
  2. constructor() {
  3. super();
  4. this.state = {
  5. n: 0,
  6. m: 0
  7. };
  8. }
  9. addN() {
  10. this.setState({ n: this.state.n + 1 });
  11. // m 会被覆盖为 undefined 吗?
  12. }
  13. addM() {
  14. this.setState({ m: this.state.m + 1 });
  15. // n 会被覆盖为 undefined 吗?
  16. }
  17. render() {
  18. return (
  19. <div className="Son">
  20. 儿子 n: {this.state.n}
  21. <button onClick={() => this.addN()}>n+1</button>
  22. m: {this.state.m}
  23. <button onClick={() => this.addM()}>m+1</button>
  24. <Grandson />
  25. </div>
  26. );
  27. }
  28. }

当其中一个值修改时,另一个值会沿用上次的值,而不会被undefined覆盖。

注意类组件的setState只会合并第一层的属性不会合并下一层的属性。案例

如果要合并可以采取 Object.assign()将第上层数据拿过来。案例

  1. const user = Object.assign({}, this.state.user);

如果要合并可以采取(…)剩余操作符将第上层数据拿过来。案例

  1. constructor() {
  2. super();
  3. this.state = {
  4. n: 0,
  5. m: 0,
  6. user: {
  7. name: "frank",
  8. age: 18
  9. }
  10. };
  11. }
  12. // 修改数据
  13. changeUser() {
  14. this.setState({
  15. // m 和 n 不会被置空
  16. user: {
  17. ...this.state.user, // 复制之前的所有属性
  18. name: "jack"
  19. // age 被置空
  20. }
  21. });
  22. }

函数组件

  1. const Grandson = () => {
  2. const [n, setN] = React.useState(0);
  3. const [m, setM] = React.useState(0);
  4. return (
  5. <div className="Grandson">
  6. 孙子 n:{n}
  7. <button onClick={() => setN(n + 1)}>n+1</button>
  8. m:{m}
  9. <button onClick={() => setM(m + 1)}>m+1</button>
  10. </div>
  11. );
  12. };

函数组件不会合并属性,案例

React事件绑定

  1. class Son extends React.Component {
  2. addN = () => this.setState({ n: this.state.n + 1 })
  3. render() {
  4. return <button onClick={this.addN}>n+1</button>
  5. }
  6. }