react 中的函数组件和类组件

505 阅读5分钟

在这里插入图片描述

react 组件

1. react 组建介绍

  • 组件特点:独立、可复用、可组合
  • react 组件,从概念上类似于 JavaScript 函数,它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 react 元素
  • 组件的实例就是调用组件函数返回的具体的页面对象

2.react 组件的两种创建方式

  • 使用函数创建组件
  • 使用 class 类创建组件

2.1 使用函数创建组件

  • 函数组件:使用 JS 的函数(或箭头函数)创建的组件

  • 约定1:函数名称必须大写字母开头

  • 约定2:函数组件必须有返回值,表示该组件的结构

  • 如果返回值为 null,表示不渲染任何内容

    function App() {
        return (
            <div>函数组件!!</div>
        )
    }
    

2.2 使用类创建组件

  • 类组件:使用 ES6 的 class 创建的组件

  • 约定1:类名称也必须以大写字母开头

  • 约定2:类组件应该继承 React.Component 父类,从而可以使用父类中提供的方法或属性

  • 约定3:类组件必须提供 render() 方法

  • 约定4:render() 方法必须有返回值,表示该组件的结构

    class App extends React.Component {
        render() {
            return (
                <div>类组件!!</div>
            )
        }
    }
    ReactDOM.render(<App />, root)
    

总结

  • 组件必须有返回值(html 结构、JSX 结构)
  • 组件名称必须以大写字母开头,react 以此区分组件和普通的 html 元素
  • 渲染时,使用组件名作为标签名

3. react 事件处理

  • 事件绑定
  • 事件对象

3.1 事件绑定

  • 传统的 HTML 绑定

    <button onclick="handleClick()">点击</button>
    
  • react 中的绑定

    <button onClick={handleClick}>点击</button>
    
  • react 事件绑定语法与 DOM 事件语法相似

    语法:on + 事件名称 = {事件处理程序},如:onClick={函数}

    注意:react 事件采用驼峰命名法,如:onMouseEnter、onClick...

  • 在函数组件中绑定事件

    function App() {
        function handleClick() {
            console.log('函数组件绑定的事件')
        }
        return (
            <button onClick={handleClick}>点击</button>
        )
    }
    
  • 在类组件中绑定事件

    class App extends React.Component {
        handleClick = () => {
            console.log('类组件绑定的事件')
        }
        render() {
            return (
                <button onClick={this.handleClick}>点击</button>
            )
        }
    }
    

3.2 事件对象

  • 可以通过事件处理程序的参数获取事件对象

  • react 中的事件对象叫做:合成事件(对象)

  • 合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题

    function App() {
        function handleClick(e) {
            e.preventDefault()
            console.log('事件对象', e)
        }
        return (
            <button onClick={handleClick}>点击不跳转页面</button>
        )
    }
    

4. 有状态组件和无状态组件

  • 数据就是状态(state),数据的变化就是状态的变化(setState())
  • 有维护自己状态存储和变化机制的组件叫做有状态组件,没有的叫做无状态组件或UI组件
  • 在 react 中,类组件是有状态组件,函数组件是无状态组件

5. 组件中的 state 和 setState()

  • state 的基本使用
  • setState() 修改状态

5.1 state 的基本使用

  • state 是数据的容器,用来存储组件内部的数据,私有的表现就是只能在组件内部使用

  • state 在类组件的构造函数中初始化,值是对象,表示一个组件中可以有多个数据

  • state 的使用,{this.state.time}

    class Timer extends React.Component {  
        constructor() {
            super()
            // 初始化组件状态(state)  
            this.state = {
                time: ’’
            }
        }
        render() {
            return (
                <div>当前时间是:{this.state.time}</div>
            )
        }
    }
    

5.2 setState() 修改数据

  • 语法 this.setState({要修改的数据})
  • setState() 作用:1. 修改 state 2. 更新UI

注意:不要直接修改 state 的值,这是错误行为

6. 事件绑定 this 指向

  • 箭头函数
  • Function.prototype.bind()
  • class 的公有字段方法

6.1 箭头函数

  • 利用箭头函数内部没有 this 的特点

  • render() 方法中的 this 为组件实例,可以获取到 setState()

    class Timer extends React.Component {  
        handleClick() {
            this.setState({ … })
        }
        render() {
            // 箭头函数中的this指向外部环境,此处为:render()方法
            return (
                <button onClick={() => this.handleClick()}></button>
            )
        }
    }
    

6.2 Function.prototype.bind()

  • 利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到一起

    class Timer extends React.Component {  
        constructor(props) {
            super(props)
            this.handleClick = this.handleClick.bind(this)
        }
            // ...省略 handleClick  
        render() {
            return (
                <button onClick={this.handleClick}></button>
            )
        }
    }
    

6.3 class 的公有字段方法

  • 利用箭头函数形式的 class 实例方法

  • 注意:该语法是实验性语法,但是,由于 babel 的存在可以直接使用

    class Timer extends React.Component {  
        handleClick = () => {
            this.setState({ … })
        }
        render() {  
            return (
                <button onClick={this.handleClick}></button>
            )
        }
    }
    

7. 表单处理

  • 受控组件
  • 非受控组件(DOM方式)

7.1 受控组件

  • HTML 中的表单元素是可输入的,也就是有自己的可变状态

  • react 中的可变状态通常保存在 state 中,并且只能通过 setState() 方法来修改

    this.state = {
        count: 0
    }
    this.setState({
        count: this.state.count + 1
    })
    
  • React 将 state 与表单元素的 value 属性绑定到一起,由 state 的值来控制表单元素的值

    <input type="text" value={this.state.count} onChange={() => this.setState({ count: this.state.count + 1 })}
     />
    
  • 受控组件:React 控制表单元素值

多表单元素优化步骤:

  1. 给表单元素添加name属性,名称与 state 相同
  2. 根据表单元素类型获取对应值
  3. 在 change 事件处理程序中通过 [name] 来修改对应的state
// 根据表单元素类型获取值
const value = target.type === 'checkbox'
        ? target.checked
        : target.value

// 根据name设置对应state  
this.setState({
    [name]: value
})

return (
<input
    type="text"
    name="count"  
    value={this.state.count}  
    onChange={this.handleForm}
/>
)

7.2 非受控组件

  1. 不受 react 中的 state 状态属性控制
  2. 借助于 ref ,使用原生 DOM 方式来获取表单元素值
  3. ref 属性作用,获取 DOM 对象或者 react 组件

使用步骤

  1. 调用 React.createRef() 方法创建一个 Refs 对象

    constructor() {  
        super()
        this.txtRef = React.createRef()
    }
    
  2. 将创建好的 Refs 对象和表单元素关联

    <input type="text" ref={this.txtRef} />
    
  3. 通过 Refs 对象的 .current 属性获取到文本框的值

    console.log(this.txtRef.current.value)
    

总结

  1. 组件的两种创建方式:函数组件和类组件
  2. 无状态(函数)组件,负责静态结构展示
  3. 有状态(类)组件,负责更新 UI ,让页面动起来
  4. 绑定事件注意 this 指向问题
  5. 推荐使用受控组件来处理表单
  6. 完全利用 JS 语言的能力创建组件,这是 React 的思想