[译] React 最佳实践

译文2016-08-270 篇评论 react JavaScript

原文 React Best Practices and Useful Functions,作者 Nessim Btesh,本文对原文有删节。

近年来,React 已经成为开发者们建立从单页应用(SPA)到移动应用的一个新工具。但是自从我开始逐步深入 React 后,我发现所有看似非常酷的 Node 模块实际上对开发有非常不利的影响。它们不遵循任何规则,组件的体积巨大。它们为几乎所有的组件都使用了状态,也包括那些根本就不作输出的组件。任何有着足够经验的人都明白,维护这样的代码会有多麻烦,以及如果每次都渲染全部组件的时候,这在浏览器上加载会有多慢。在这篇文章中,我会带你探索 React 的最佳实践,包括如何设置 React 以及如何让它变得足够快。

在你开始阅读前请注意:React 是一个函数式编程(Functional Programming,FP)库,如果你不知道函数式编程是什么,请阅读其它相关文章。

使用 ES6(通过 Babel 进行编译):ES6 会让你的工作变得更容易许多,它使得 JS 不管是看起来还是感觉起来都更加的现代化。一个非常好的 ES6 的例子是 Generator 和 Promis,记住当你需要做大量的嵌套调用的时候,你可以使用它们来进行异步调用。下面来介绍下同步和异步 JS,这是有关 Generator 的一个示例:

getJSON(url, function(response) {
    getJSON(url, function(response) {
      console.log(response);
    });
});

可以转变为这样的形式:

function* getStockValue() {
    var entry1 = yield request('http://myrl.com/stock/key');
    var data1  = JSON.parse(entry1);
    var entry2 = yield request('http://myurl/stock/value');
    var data2  = JSON.parse(entry2);
}

使用 Webpack:使用 Webpack 的理由很简单:热重载,压缩文件,Node 模块加载,以及你可以把你的应用进行分片,从而可以进行延迟按需加载。

总是注意你的打包文件大小 :让你的打包文件变小的一个途径是从 Node 模块相应目录直接导入:

// 像这样做
import Foo from ‘foo/Foo’

// 而不是像这样做
import {Foo} from ‘foo’

使用 JSX 语法 :如果你有 Web 开发的背景,JSX 语法会让你感觉很自然。但是如果你的背景不是 Web 开发,你也不用太担心,JSX 非常容易学习。 注意 如果你不使用 JSX 语法进行开发的话,代码维护会变得异常艰难。

保持你的组件微型化(非常微小):最佳实践证明如果你的渲染函数超过 10 行就可能太大了,使用 React 的主要思想就是代码重用,所以如果你只是把所有的代码都扔到一个文件里面去,你就会失去 React 的优雅。

使用 ShouldComponentUpdate 方法 :React 是一个模板语言,在每次组件状态改变的时候都会进行渲染操作,所以想象一下每当页面中有动作发生时,整个页面都要被重新渲染,这会花费浏览器很长的加载时间。这就是 ShouldComponentUpdate 方法 出现的原因,当 React 要重新渲染每一个组件时都要检查它 ShouldComponentUpdate 方法返回的结果是 false 还是 true。所以只要你的组件是完全静态的,为了你自己着想,你应该返回 false。如果组件不是静态的话,就检查它的的 props 或者 state 是否发生了改变。

使用无状态组件 :不需要在每一个组件内部存储状态这一点已经不必多说,理想的情况下,你应该有一个全功能的父组件,并且里边所有的子组件都应该是无状态的,只是接收传来的 props 并且在里边没有任何的逻辑处理。你能够像这样来创建一个无状态组件:

const DumbComponent = ({props}) => {
  return (<div />);
}

无状态组件也非常容易调试,因为它坚持自顶向下的思想,而这正是 React 的全部。

总是在构造方法中对函数进行绑定 :任何有状态的组件都要尽量在构造方法中进行函数绑定。

export default class BindFunctionExample extends React.Component {
    constructor() {
        super();
        this.state = {
            hidden: true,
        };
        this.toggleHidden = this.toggleHidden.bind(this);
    }

    toggleHidden() {
            const hidden = !this.state.hidden;
            this.setState({hidden})
    }

    render(){
        return(
            <button onClick={this.toggleHidden} />
        );
    }
}

使用 Redux/Flux:处理数据时,你应该使用 Flux 或者 Redux。Flux/Redux 允许你处理方便地处理数据以及远离因处理前端缓存时候而产生的病痛。我个人使用 Redux 因为它强制你对文件目录结构有更好的安排。

使用 Normalizr:既然我们谈到了数据,我想花一些时间来介绍一下处理复杂数据结构的最佳方式。Normalizr 可以把你的嵌套 json 对象格式化成为简单的数据结构,让你能够很方便的对数据进行操作。

文件目录结构 :在这直言不讳地说,我只看过两种文件目录结构,通过 React/Redux 使得一切变得简单:

第一种文件目录结构:

first-structure

第二种文件目录结构:

second-structure

使用 Container:你应该避免把每一个组件与 Flux/Redux 的 Store 直接连接起来,这就是你应该使用 Container 为下层传递数据的原因。最好的方式是创建两个 Container:一个包含所有的安全组件(需要认证的组件),另一个包含所有的不安全组件。创建一个父 Container 的最好方式是克隆所有子节点并且把期望的 Props 传递下去:

class Container extends React.Component {
    render(){
        var { props } = this;
        return(
                <div className="main-content">
                    {  
                        React.Children.map(this.props.children, function(child) {
                            return React.cloneElement(
                                child, 
                                { ...props }
                            );
                        })
                    }
                </div>
        );
    }
}

const mapStateToProps = (state) => {
    return state;
};

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(actions, dispatch)
    };
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Container);

(以下是译者的补充)

使用 Immutable.js 作为 Redux 中 Store 的数据结构 Immutable.js 即为不可变数据结构,在判断对象是否相等时,可以通过最外层引用级别的比较来替代复杂的深层比较,用在 ShouldComponentUpdate 方法中能够极大地提升性能。另外,具有函数式编程特性的 Immutable.js 能够非常方便地对数据进行处理,如查找、排序、合并、删除等等,与 Normalizr 搭配使用能够极大地提升开发效率,值得使用。对于 Immutable.js 的介绍可看我另一篇译文 《Immutable.js 介绍与函数式编程概念》

评论区

发表评论
用户名
(必填)
电子邮箱
(必填)
个人网站
(选填)
评论内容
Copyright © 2017 dremy.cn
皖ICP备16015002号