const div = React.createElement('div', null) 是一个元素

const Div = () => React.createElement('div', null)是一个组件(就是一个回调),首字母大写

在 React 中,HTML

等标签会被翻译成 React.creatElement(‘div’)

函数组件

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

类组件

  1. class Hello extends React.Component {
  2. constructor() {
  3. super()
  4. this.state = {n: 0}
  5. }
  6. render() {
  7. return <h1> Hi, {this.props.name} </h1>
  8. }
  9. }
  10. // 使用 <Hello name="Dudu" />

内部数据 state

类组件:用 this.state.n 读,用 this.setState({n: this.state.n+1}) 写(异步更新 )

函数组件:[n, setN] = useState(0),n 为数据,setN 为设置函数,0 为 n 的初始值

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import './style.css';
  4. function App() {
  5. return (
  6. <div className='father'>
  7. father
  8. <Son />
  9. </div>
  10. );
  11. }
  12. class Son extends React.Component {
  13. constructor() {
  14. super();
  15. this.state = { n: 0 };
  16. }
  17. add() {
  18. // 不能直接 this.state.n += 1,react 不监听数据
  19. // this.setState({ n: this.state.n + 1 }); // 产生一个新对象
  20. // 由于 this.setState 为异步更新,若要实实时打印n,一般使用函数
  21. this.setSate((state) => {
  22. const n = state.n + 1;
  23. console.log(n);
  24. return {n};
  25. })
  26. }
  27. render() {
  28. return (
  29. <div className='son'>
  30. Son n: {this.state.n}
  31. <button onClick={() => {
  32. this.add()
  33. }}> +1 </button>
  34. <Grandson />
  35. </div>
  36. );
  37. }
  38. }
  39. const Grandson = () => {
  40. // n 的初始值为0,setN 不改变 n ,setN 后得到一个新的 n
  41. const [n ,setN] = React.useState(0);
  42. return (
  43. <div className='grandson'>
  44. Grandson n: {n}
  45. <button onClick={() => setN(n + 1)}>+1</button>
  46. </div>
  47. );
  48. }
  49. const root = document.querySelector('#root');
  50. ReactDOM.render(<App />, root);

1.png

多个 state 数据的情况

以下为个人理解,极大可能理解错误,待考证
有多个 state 数据时,React 将新旧虚拟DOM 不一致的部分包括其子组件一起重渲染,对于没有变化的数据,渲染时只会保留栈内存中的数据,而不保留堆内存中的数据(因为栈内存中的地址改变了,React 会重新创建一个对象,对象中没有改动的数据不在这个新对象中,就会变成 undefined)
也就是说,React 局部重渲染的是新旧虚拟DOM表示的DOM中数据的栈内存中不一致的数据
具体原理看 useState 原理

  • 数据在栈内存时:

类组件:

  1. class MyCompnent extends React.Component {
  2. constructor() {
  3. super();
  4. this.state = {
  5. n: 0
  6. m: 0
  7. }
  8. }
  9. addN() {
  10. // 改变 n 的值,重渲染后 m 的值不变
  11. this.setState({ n: this.state.n + 1 });
  12. }
  13. addM() {
  14. // 改变 m 的值,重渲染后 n 的值不变
  15. this.setState({ m: this.state.m + 1 });
  16. }
  17. }

函数组件

  1. const MyComponent = () => {
  2. const [n, setN] = React.useState(0);
  3. const [m, setM] = React.useState(0);
  4. // 改变 n 的值,重渲染后 m 的值不变
  5. // 改变 m 的值,重渲染后 n 的值不变
  6. return (
  7. <div>
  8. n: {n} <button onClick={() => setN(n + 1)}></button>
  9. m: {m} <button onClick={() => setN(m + 1)}></button>
  10. </div>
  11. )
  12. }
  • 栈内存中为地址,数据在堆内存时

类组件

  1. class MyCompnent extends React.Component {
  2. constructor() {
  3. super();
  4. this.state = {
  5. num: {
  6. n: 0,
  7. m: 0
  8. }
  9. }
  10. }
  11. addN() {
  12. // 改变 n 的值,重渲染后 m 的值变为 undefined
  13. this.setState({
  14. num: {n: 0}
  15. });
  16. }
  17. addM() {
  18. // 改变 m 的值,重渲染后 n 的值变为 undefined
  19. this.setState({
  20. num: {m: 0}
  21. });
  22. }
  23. }

函数组件:

  1. const MyComponent = () => {
  2. const [state, setState] = React.useState({n:0, m:0});
  3. // 改变 n 的值,重渲染后 m 的值变为 undefined
  4. // 改变 m 的值,重渲染后 n 的值变为 undefined
  5. return (
  6. <div>
  7. n: {state.n} <button onClick={() => setState({n: state.n + 1})}></button>
  8. m: {state.m} <button onClick={() => setState({m: state.m + 1})}></button>
  9. </div>
  10. )
  11. }

解决方法:使用 ‘…’ 操作符号

  1. // 类组件
  2. addN() {
  3. this.setState({
  4. ...this.state.num,
  5. num: {n: 0}
  6. });
  7. }
  8. // 函数组件
  9. <button onClick={() => setState({...state, n: state.n + 1})}></button>

外部数据 props

类组件:用 this.props.n 读

函数组件:直接读取传入参数 props.n

传 props 属性用 “” 或 {}

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import './style.css';
  4. function App() {
  5. return (
  6. <div className='father'>
  7. father
  8. {/* <Son messageForSon={1 + 1} /> */}
  9. <Son messageForSon="Hi, my son!" />
  10. </div>
  11. );
  12. }
  13. // 类组件
  14. class Son extends React.Component {
  15. render() {
  16. return (
  17. <div className='son'>
  18. Father to Son: {this.props.messageForSon}
  19. <Grandson massageForGrandson="Hi, son!" />
  20. </div>
  21. );
  22. }
  23. }
  24. // 函数组件
  25. const Grandson = (props) => {
  26. return (
  27. <div className='grandson'>
  28. Father to Son: {props.massageForGrandson}
  29. </div>
  30. );
  31. }
  32. const root = document.querySelector('#root');
  33. ReactDOM.render(<App />, root);

2.png