美文网首页
react生成组件的常用方法

react生成组件的常用方法

作者: 好奇而已 | 来源:发表于2020-12-02 22:23 被阅读0次

    基于 Class 的组件最佳实践(Class Based Components)

    基于 Class 的组件是状态化的,包含有自身方法、生命周期函数、组件内状态等。最佳实践包括但不限于以下一些内容:

    1)引入 CSS 依赖 (Importing CSS)

    我很喜欢 CSS in JavaScript 这一理念。在 React 中,我们可以为每一个 React 组件引入相应的 CSS 文件,这一“梦想”成为了现实。在下面的代码示例,我把 CSS 文件的引入与其他依赖隔行分开,以示区别:

    import React, {Component} from 'react'
    import {observer} from 'mobx-react'
    
    import ExpandableForm from './ExpandableForm'
    import './styles/ProfileContainer.css'
    
    

    当然,这并不是真正意义上的 CSS in JS,具体实现其实社区上有很多方案。我的 Github 上 fork 了一份各种 CSS in JS 方案的多维度对比,感兴趣的读者可以参考这里:HOUCe/css-in-js

    2)设定初始状态(Initializing State)

    在编写组件过程中,一定要注意初始状态的设定。同时,利用 ES6 模块化的知识,我们确保该组件暴露都是 “export default” 形式,方便其他模块(组件)的调用和团队协作。

    import React, {Component} from 'react'
    import {observer} from 'mobx-react'
    
    import ExpandableForm from './ExpandableForm'
    import './styles/ProfileContainer.css'
    
    export default class ProfileContainer extends Component {
        state = { expanded: false }
        ......
    
    

    3)设定 propTypes 和 defaultProps

    propTypes 和 defaultProps 都是组件的静态属性。在组件的代码中,这两个属性的设定位置越高越好。因为这样方便其他阅读代码者或者开发者自己 review,一眼就能看到这些信息。这些信息就如同组件文档一样,对于理解或熟悉当前组件非常重要。

    同样,原则上,你编写的组件都需要有 propTypes 属性。如同以下代码:

    export default class ProfileContainer extends Component {
        state = { expanded: false }
    
        static propTypes = {
            model: React.PropTypes.object.isRequired,
            title: React.PropTypes.string
        }
    
        static defaultProps = {
            model: {
                id: 0
            },
            title: 'Your Name'
        }
    
    

    Functional Components 是指没有状态、没有方法,纯组件。应该最大限度地编写和使用这一类组件。这类组件作为函数,其参数就是 props, 我们可以合理设定初始状态和赋值。

    function ExpandableForm({ onExpand, expanded = false, children, onSubmit }) {
        const formStyle = expanded ? {height: 'auto'} : {height: 0}
        return (
            <form style={formStyle} onSubmit={onSubmit}>
                {children}
            <button onClick={onExpand}>Expand</button>
            </form>
        )
    }
    
    

    4)组件方法(Methods)

    在编写组件方法时,尤其是你将一个方法作为 props 传递给子组件时,需要确保 this 的正确指向。我们通常使用 bind 或者 ES6 箭头函数来达到此目的。

    export default class ProfileContainer extends Component {
        state = { expanded: false }
    
        handleSubmit = (e) => {
            e.preventDefault()
            this.props.model.save()
        }
    
        handleNameChange = (e) => {
            this.props.model.changeName(e.target.value)
        }
    
        handleExpand = (e) => {
            e.preventDefault()
            this.setState({ expanded: !this.state.expanded })
        }
    
    

    当然,这并不是唯一做法。实现方式多种多样,我专门有一片文章来对比 React 中对于组件 this 的绑定,可以参考:从 React 绑定 this,看 JS 语言发展和框架设计

    5)setState 接受一个函数作为参数(Passing setState a Function)

    在上面的代码示例中,我们使用了:

    this.setState({ expanded: !this.state.expanded })
    
    

    这里,关于 setState hook 函数,其实有一个非常“有意思”的问题。React 在设计时,为了性能上的优化,采用了 Batch 思想,会收集“一波” state 的变化,统一进行处理。就像浏览器绘制文档的实现一样。所以 setState 之后,state 也许不会马上就发生变化,这是一个异步的过程。

    这说明,我们要谨慎地在 setState 中使用当前的 state,因为当前的state 也许并不可靠。 为了规避这个问题,我们可以这样做:

    this.setState(prevState => ({ expanded: !prevState.expanded }))
    
    

    我们给 setState 方法传递一个函数,函数参数为上一刻 state,便保证setState 能够立刻执行。

    关于 React setState 的设计, Eric Elliott 也曾经在一篇文章中这么喷过:https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82#.ftefj7nn2, 并由此展开了多方“撕逼”。作为围观群众,我们在吃瓜的同时,一定会在大神论道当中收获很多思想,建议阅读。

    引用文章
    引用文章

    相关文章

      网友评论

          本文标题:react生成组件的常用方法

          本文链接:https://www.haomeiwen.com/subject/xsalwktx.html