React中创建组件的方式

特别声明:小站已开通年费VIP通道,年费价格为 ¥365.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)

学习React也有一段时间了,虽然天天都在围绕着组件打转转,但在React中怎么构建组件呢并没有去深入的了解。事实上呢?在React中的组件还是有些复杂的,从概念上来说就不简单。比如说,类组件函数组件无状态组件高阶组件等。另外创建组件的方式也有所不同,比如最早使用React.createClass来创建组件,有了ES6之后使用extends React.Component(借助ES6的class特性)创建组件,而今天又流行使用函数(Hooks)方式来创建组件。那么他们之间如何创建组件,又有何区别呢?在这篇文章中我们就先来学习和探讨在React中如何创建组件。

先来看React.createClass如何创建组件?

React.createClass

如果你一直以来都在使用React的话,那么对React.createClass这个API并不陌生。在React中,最初就是用这个API来创建React组件。将描述组件的所有信息都将作为对象传递给createClass

createClass方法为开发人员提供了一个工厂方法(Factory Method),可以在不使用JavaScript 类的情况下创建React类组件。这是在ES之前创建React组件方法之一,因为在ES5中没有可用的类语法:

const App = React.createClass({
    getInitialState: function() {
        return {
            value: '大漠'
        }
    }

    onChange: function(e) {
        this.setState({
            value: e.target.value
        })
    }

    render: function() {
        return (
            <div className="card">
                <h1>使用 React.createClass 创建组件</h1>
                <input 
                    value={this.state.value}
                    type="text"
                    onChange={this.onChange}
                />
                <p>Hello, {this.state.value} (^_^)!</p>
            </div>
        )
    }
})

const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);

上面的Demo在React V15.5版本上运行。

createClass()方法接受一个对象,该对象为React组件定义方法。getInitialState()函数用于为React组件设置初始状态,强制使用render()方法在JSX中用于输出;额外的方法(比如onChange)是通过向对象传递更多的函数而添加的。

React中的生命周期也是可用的。例如,为了每次将值从input中输入存到浏览器的本地存储中(localStorage),我们可以使用componentDidUpdate()生命周期,该方法是将一个函数传递给对象,对象键以React的生命周期方法命名。此外,当组件接收到初始状态时,可以从本地存储中读取该值:

const App = React.createClass({
    getInitialState: function() {
        return {
            value: localStorage.getItem('userName') || '@大漠'
        }
    },
    componentDidUpdate: function(){
        localStorage.setItem('userName', this.state.value)
    },
    onChange: function(e) {
        this.setState({
            value: e.target.value
        })
    },
    render: function() {
        return (
            <div className="card">
                <h1>使用React.createClass创建组件</h1>
                <input 
                    type="text"
                    value={this.state.value}
                    onChange={this.onChange}
                />
                <p>Hello, {this.state.value} (^_^)!</p>
            </div>
        )
    }
})

const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);

这个示例具有本地存储的功能,每当重新加载或刷新浏览器时,当组件第一次挂载时,应该会显示之前在input中输入的本地存储的初始状态。

注意:React核心包中不再提供React.createClass()方法。如果你想尝试它,必须安装一个额外的包:npm i create-react-class。时至今日,应该尽可能地避免使用它。在这里可以获取到React.createClass()创建组件更多的信息

React Mixins

React中引入了React Mixins,作为React的第一个可重用组件逻辑,这是一种高级模式。使用Mixin,可以将React组件的逻辑提取出来成为一个独立对象。当在组件中使用Mixin时,所有来自Mixin的特性都被引入组件:

var localStorageMixin = {
    getInitialState: function(){
        return {
            value: localStorage.getItem('userName') || '@大漠'
        }
    },
    setLocalStorage: function(val) {
        localStorage.setItem('userName', val)
    }
}

var App = React.createClass({
    mixins: [localStorageMixin],
    componentDidUpdate: function(){
        this.setLocalStorage(this.state.value)
    },
    onChange: function(e) {
        this.setState({
            value: e.target.value
        })
    },
    render() {
        return (
            <div className="card">
                <h1>使用React Mixin和createClass创建组件</h1>
                <input 
                    type="text"
                    value={this.state.value}
                    onChange={this.onChange}
                />
                <p>Hello, {this.state.value} (^_^)!!!</p>
            </div>
        )
    } 
})

const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);

本例中,Mixin提供从本地存储中读取组件的初始状态,并使用setLocalStorage()方法扩展组件,该方法稍后将在实际组件中使用。为了使用Mixin更加灵活,我们可以使用一个函数来返回一个对象:

function getLocalStorageMixin(localStorageKey) {
    return {
        getInitialState: function(){
            return {
                value: localStoragee.getItem(localStorageKey) || ''
            }
        },
        setLocalStorage: function(value) {
            localStorage.setItem(localStorageKey, value)
        }
    }
}

var App = React.createClass({
    mixins: [getLocalStorageMixin('userName')],
    // ...
})

注意:现在在React中不再使用Mixins了,因为它们有几个缺点。有关于React Mixins更多的信息,可以点击这里进行了解

createClass()是创建React组件的一种简单而有效的方法。React最初使用createClass API的原因是,当时JavaScript没有内置的class。当然,这种情况最终改变了。ES6开始引入了class这个关键字,也可以使用类来创建组件。这让React进入了一个两难的境地,要么继续使用createClass,要么跟进ES6,使用class来创建组件。事实证明,React选择了后者。

React.Component

React v3.13.0版本引入了React.Component API,允许你使用JavaScript的类(class)来创建React组件。在React中使用class创建的组件常常被称为React 类组件

我们可以使用React.Component来重构上面使用React.createClass()方法创建的组件。

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: localStorage.getItem('userName') || '@大漠'
        }
        this.onChange = this.onChange.bind(this)
    }

    componentDidUpdate() {
        localStorage.setItem('userName', this.state.value)
    }

    onChange(e) {
        this.setState({
            value: e.target.value
        })
    }

    render() {
        return (
            <div className="card">
                <h1>使用ES6 Class创建组件(React.Component)</h1>
                <input 
                    type="text"
                    value={this.state.value}
                    onChange={this.onChange}
                />
                <p>Hello, {this.state.value} (^_^)!!!</p>
            </div>
        )
    }
}

const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);

使用JavaScript类编写React组件带有类构造函数constructor()(主要用于React中设置初始状态或绑定方法)和render()方法。React组件内部所有逻辑都来自于React.Component。通过类组件中使用面向对象继承的组件。但是,不建议在更多的地方使用继承这个概念。相反,建议使用组合而不是继承

在React中使用React.Component创建组件,有几个重要的概念需要掌握。

构造函数 constructor()

使用类组件,可以在构造函数constructor()内部将组件的状态初始化为实例(this)上的状态属性。但是,根据ECMAScript规范,如果要扩展子类(即React.Component),必须要先调用super(),然后才能使用this。具体来说,在使用React时,还必须记住将props传递给super()

class App extends React.Component {
    constructor(props) {
        super(props)
        // ...
    }
    // ...
}

自动绑定

当使用React.createClass创建组件时,React会自动将所有方法绑定到组件的实例(this。而React.Component并非如此,很多开发人员都意识到他们不知道this关键字是如何工作的。因为必须记住类构造函数中的.bind()方法(即.bind(this)。如果不这样做的话,浏览器会报“无法读取未定义的setState属性”错误。

class App extends React.Component {
    constructor(props) {
        super(props)
        //...
        this.onChange = this.onChange.bind(this)
    }
    // ...
}

调用super(props)并要记住.bind(this)方法是比较烦人,但这里并没有什么根本的错误。但当你一天要像这样处理很多次的时候,也会令人感到烦感。庆幸的是,在从createClass切换到React.Component之后不久,TC39就提出Class Fields相关的建议

类字段(Class Fields)

类字段允许我们直接将实例属性作为属性添加到类上,而无需使用构造函数。这样一来,我们就不再需要使用构造函数来设置组件的初始状态,也不再需要在构造函数中使用.bind(this),因为我们可以使用箭头函数。

class App extends React.Component {
    state = {
        value: localStorage.getItem('userName') || '@w3cplus'
    }

    componentDidUpdate() {
        localStorage.setItem('userName', this.state.value)
    }

    onChange = (e) => {
        this.setState({
            value: e.target.value
        })
    }

    render () {
        const {value} = this.state

        return (
            <div className="card">
                <h1>使用React.Component创建组件(Class Fields)</h1>
                <input 
                    type="text"
                    value={value}
                    onChange={this.onChange}
                />
                <p>Hello, {value} (^_^)!!!</p>
            </div>
        )
    }
}

const rootElement = document.getElementById("app");
ReactDOM.render(<App />, rootElement);
剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/react/how-to-create-component-in-react.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部