React类组件和函数组件

169 阅读2分钟

组件(Component)

Element V.S. Component

元素与组件

  • const div = React.createElement('div', ...)
  • 这是一个 React 元素(d小写)
  • const Div = ()=>React.createElement(''div), ...
  • 这是一个 React 组件(D大写)

什么是组件

  • 一个返回 React 元素的函数就是组件
  • 在 Vue 里, 一个构造选项就可以表示一个组件

React 两种组件

  • 函数组件
    function Welcome(props) {
        return <h1>Hello, {props.name}</div>;
    }
  • 使用方法: <Welcome name = 'ivan'>
  • 类组件
    class Welcom extends React.Component {
        render() {
            return <h1> Hello, {this.props.name} <h1>
        }
    }
  • 使用方法: <Welcome name = "ivan">

标签会被翻译为 React.createElement

会被翻译成什么

  • <div />会被翻译成 React.createElement('div')
  • <Welcome />翻译为 React.createElement(Welcome)
  • 可以用 babel 尝试一下

image.png

React.createElement 的逻辑

  • 如果传入一个字符串'div', 则会创建一个 div
  • 如果传入一个函数, 则会调用该函数, 获取其返回值
  • 如果传入一个类, 则在类前面价格 new (这会导致执行 constructor) , 获取一个组件对象, 然后调用对象的 render 方法, 获取其返回值

类组件和函数组件使用 props

添加 props (外部数据)

  • 类组件直接读取属性 this.props.xxx
  • 函数组件直接读取参数 props.xxx

image.png

添加 state (内部数据)

  • 类组件用 this.state 读, this.setState 写

  • this.setState 不会马上去改变 this.state, 最好用函数去区分state的新旧 image.png

  • 函数组件用 useState 返回数组, 第一项读, 第二项写

  • setN 永远不会改变 this.state.n

image.png

类组件注意事项

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, 一律用参数和变量

复杂 state

如果 state 里不止有 n 怎么办

  • 类组件里有 n 和 m
  • 函数组件里有 n 和 m image.png

总结

  • 类组件的 setState 会自动合并第一层属性
  • 但是并不会合并第二层属性
  • 可以使用 Object.assign 或者 ...操作符
  • 函数组件的 setX 则完全不会帮你合并(可使用...操作符使其合并)

image.png

事件绑定

类组件的事件绑定

  • <button onClick={()=> this.add()}>n+1</button>
    • 传一个函数给 onClick 即可, 注意 C 大写
  • this.addN = ()=> this.setState({ n: this.state.n + 1 });

image.png

  • addN = ()=> this.setState({ n: this.state.n + 1 });
    • 绑定事件的最终写法 image.png