前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小结React(二):组件知多少

小结React(二):组件知多少

原创
作者头像
前端林子
修改2019-04-20 19:33:09
2.5K0
修改2019-04-20 19:33:09
举报
文章被收录于专栏:前端技术总结前端技术总结

0.引入

React 16.8中正式发布了React Hooks,主要是想解决如何复用一个有状态的组件的问题。实际上React Hooks就是一系列特殊的函数,可以让本来无状态的函数组件变成有状态的,在组件内部hook组件的状态state和lifecycle。不过在正式总结React Hooks前,有必要搞清楚一些比较基本的问题,例如:什么是组件,什么是有状态组件和无状态组件,它们各自有什么特点,如何创建组件。本文根据这一思路将梳理关于React组件的基本内容,具体包括:

1.什么是组件

React的一个核心思想就是把页面拆分成一个个独立、可重用的组件,并且用自上而下的单向数据流将这些组件串联起来,在React中是这样定义组件的:

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

就是说通过使用组件 可以把页面拆分为独立的、可重用的部分,并可以单独地考虑每个部分。

另外注意在React中组件名称必须以大写字母开头,React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome。

2.定义React组件的方式

React定义React组件的方式:

2.1函数组件

(1)出现版本:从React 0.14开始出现,可点击

(2)组件形式:函数组件是无状态的组件,只根据传入的属性props做展示、带有render方法。没有state状态的操作、没有生命周期lifecycle,可通过函数形式或者ES6的箭头函数创建。

代码语言:javascript
复制
// 1,函数组件
function Welcome(props) {
    return <h1>Hello, {props.name}</h1>
}
ReactDOM.render(<Welcome name="Peter" />, document.getElementById('root'))

(3)函数组件的特点:

总的来说,React的建议是

This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps.

只要有可能,尽量使用无状态组件。

2.2类组件

提前说明:如果想创建一个类组件,请使用ES6的React.Component的形式来创建。

2.2.1ES5定义类组件的方式--React.createClass

(1)说明:这是React刚开始推荐的创建组件的方式。是ES5的原生的JavaScript来实现的React组件。再次强调,React更推荐用React.Component的方式去创建有状态的组件。

(2)组件形式:类组件是有状态的组件,自然组件要被实例化,且可以访问state、lifecycle。

示例:

代码语言:javascript
复制
// 2,React.createClass
import React from 'react'
import ReactDOM from 'react-dom'
const SwitchButton = React.createClass({
    getDefaultProp: function () {
        return {
            open: false
        }
    },
    // 返回初始的state
    getInitialState: function () {
        return {
            open: this.props.open
        };
    },
    handleClick: function (event) {
        this.setState({
            open: !this.state.open
        });
    },
    render: function () {
        var open = this.state.open,
            className = open ? 'switch-button open' : 'switch-button';
        return (
            <label
                className={className}
                onClick={this.handleClick}>
                <input type="checkbox" checked={open} />开
            </label>);
    }
});
ReactDOM.render(<SwitchButton />, document.getElementById('root'));

(3)React.createClass的特点:

2.2.2ES6定义类组件的方式--React.Component

(1)说明:是以ES6的方式来创建React组件

(2)组件形式

示例,上述代码用ES6的React.Component实现:

代码语言:javascript
复制
// 3,React.Component
import React from 'react'
import ReactDOM from 'react-dom'
class SwitchButton extends React.Component {
    constructor(props) {
        super(props)
        // 返回初始的state,相当于ES5中的getInitailState
        this.state = {
            open: this.props.open
        }
        // 这句要注意,React.component中函数不会自动绑定this,要手动绑定
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick(event) {
        this.setState({
            open: !this.state.open
        })
    }
    render() {
        let open = this.state.open, className = open ? 'switch-button open' : 'switch-btn'
        return (
            <label
                className={className}
                onClick={this.handleClick}>
                <input type="checkbox" checked={open} /> 开
            </label>)
    }
}
// 相当于React.createClass中的getDefaultProps
SwitchButton.defaultProps = {
    open: false
}
ReactDOM.render(<SwitchButton />, document.getElementById('root'))

需要注意,React.component中函数不会自动绑定this,要手动绑定。有三种手动绑定的方式:

-- 在构造函数中绑定,就是上述示例中采用的方法:

代码语言:javascript
复制
constructor(props) {
    super(props)
    this.state = {
        ...
    }
    this.handleClick = this.handleClick.bind(this)
}

-- 在调用时绑定:

代码语言:javascript
复制
onClick={this.handleClick.bind(this)}

-- 使用ES6的箭头函数来绑定:

代码语言:javascript
复制
onClick={()=>this.handleClick()}

(3)React.Component的特点:

2.2.3React.createClass和React.Component如何选择?

The most notable new feature is support for ES6 classes , which allows developers to have more flexibility when writing components. Our eventual goal is for ES6 classes to replace React.createClass completely, but until we have a replacement for current mixin use cases and support for class property initializers in the language, we don’t plan to deprecate React.createClass.

可以看出React更推荐以React.Component的形式来创建一个有状态的组件,React.Component最终会完全取代React.createClass。但在找到Mixins的替代方案前,不会废弃掉React.createClass。不过9102年了,在HOC、Render Props、React Hooks这些解决方案都出现的今天,Mixins已被开发团队坚决地舍弃了。总的来说,现在要创建一个有状态的组件,请用React.Component的形式来创建。

2.2.4 函数组件和React.Component如何选择

1,尽可能使用函数组件创建;

2,除非需要state、lifecycle等,使用React.Component这种ES6的形式创建有状态的类组件;

3,如果想在函数组件中使用state、lifecycle,使用React Hooks;

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

上面已经说过,函数组件是无状态的组件,类组件是有状态的组件。

React中有五类API:

  • render
  • state
  • props
  • context
  • lifecycle events

有状态的组件:组件内部可以使用状态(state)、生命周期(lifecycle)、render

无状态的组件:组件内部可以使用属性(props)、context、render。

更多关于React组件模式的内容,可以阅读 React组件模式

4.受控组件和非受控组件

所谓受控组件、非受控组件,都是针对form表单而言的。

4.1受控组件

受控组件就是表单元素有当前值(value),同时还有一个回调函数(onChange)可以改变这个值,回调函数中通过使用setState()更新对应的state值,示例:

代码语言:javascript
复制
// 受控组件
import React from 'react'
class Form extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
        };
    }

    handleNameChange = (event) => {
        // 在回调函数中用event.target.value获取新的值
        this.setState({
            name: event.target.value
        });
    };

    render() {
        return (
            <div>
                <input
                    type="text"
                    value={this.state.name}
                    onChange={this.handleNameChange}
                />
            </div>
        );
    }
}

4.2非受控组件

非受控组件是不受状态的控制,可以使用defaultValue、defaultChecked设置初始值,使用ref来获取DOM的值。

代码语言:javascript
复制
<input
    type="text" 
    defualtValue="Peter" 
    ref={input => this._name = input} 
/>

形式上,如果是通过value属性、checked属性来设置表单元素的值,那么表单元素就是受控的。如图,右边是受控的:

5.小结

万丈高楼平地起,作为介绍React Hooks的基础篇,本文主要梳理了什么是组件、三种创建组件的方式,各自的特点,以及如何进行选择。接下来总结了什么是有状态组件、无状态组件、受控组件和非受控组件。如有问题,欢迎指正。

6.参考文章:

[1]http://www.cnblogs.com/wonyun/p/5930333.html

[2]https://medium.com/teamsubchannel/react-component-patterns-e7fb75be7bb0

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0.引入
  • 1.什么是组件
  • 2.定义React组件的方式
    • 2.1函数组件
      • 2.2类组件
        • 2.2.1ES5定义类组件的方式--React.createClass
        • 2.2.2ES6定义类组件的方式--React.Component
        • 2.2.3React.createClass和React.Component如何选择?
        • 2.2.4 函数组件和React.Component如何选择
    • 3.有状态组件和无状态组件
    • 4.受控组件和非受控组件
      • 4.1受控组件
        • 4.2非受控组件
        • 5.小结
        • 6.参考文章:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档