React.js的经验教训和一些有观点的最佳实践

172 阅读3分钟

React.js的经验教训和一些有观点的最佳实践。这是我从React.js开发中所学到的所有东西的一个持续的汇编和进行中的工作。

基本组件组织

React.createClass({
    propTypes: {},
    mixins: [],

    getInitialState(){},
    getDefaultProps(){},

    componentWillMount(){},
    componentWillReceiveProps(){},
    // Store removeChangeListener
    componentWillUnmount(){},
    // Third-party code initialization here...
    // Store addChangeListener here...
    componentDidMount(){},

    _parseData(){},
    _onSelect(){},
    _onChange(){},

    render(){}
});

Flux模式技巧

商店

  • 存储器不一定只代表数据。它们也可以代表应用程序的状态,如模版是否显示/隐藏,或用户是否在线/离线等。
  • 商店可以而且可能需要使用来自其他商店的数据。在调度器中使用waitFor方法。
  • 商店不应该包含在服务器上获取自己的逻辑;最好是使用DAO(数据访问对象)来获取数据,它是薄层包装的API对象。

行动

  • 行动应该被分成两种类型:视图行动和服务器行动。这将把用户交互(如点击按钮)与检索数据分开。
  • 动作应该是 "发射 "和 "遗忘 "的,不能有回调。如果你需要对一个动作的结果做出反应,你应该监听一个完成或错误事件

个人头脑风暴

专注于公共动作。简单性是关键。不要把执行放在最前面。

对于react来说,虽然它促进了一个在架构上更合理的应用,但由于html和javascript的耦合,它确实促进了难以管理的代码。HTML文件越来越大,主要是因为HTML的冗长,而逻辑和模块界面很容易在这个过程中丢失。

使用传播操作符,让孩子继承父母的道具。注意,这里的规范顺序很重要。后面的属性会覆盖前面的属性。

var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />

使用命名的组件,使组件更简单,更容易阅读。

var MyFormComponent = React.createClass({});

MyFormComponent.Row = React.createClass({});
MyFormComponent.Label = React.createClass({});
MyFormComponent.Input = React.createClass({});

//...

var Form = MyFormComponent;
var App = (
    <Form>
        <Form.Row>
            <Form.Label />
            <Form.Input />
        </Form.Row>
    </Form>
);

状态

对状态的道具进行重复的问题

这是一个有些复杂的事情。进入状态的东西会变得更加复杂,因为有可能要复制道具......这样就可以在表单中进行编辑。

setState不能处理复杂的对象,使得{ data:{}, errors:{}}不是一个可行的架构,怎么办?现在该如何处理表单呢?

一定有更好的方法......React.addons.update不应该被使用。它是不方便的,而且是一个黑客。

状态应该只是一个单层对象。它不应该有孙子,否则它将变得不可维护。有更多的反应模块比不方便的代码更好。

有意见的约定

JSX转换的内联迭代。过多的移动光标等会降低流程。但是部分可以被划分为变量。

组件应该尽可能地转储。所有的逻辑都应该存在于商店或服务中。组件必须包含的唯一东西是行动、事件处理程序和HTML。组件真的只是愚蠢的视图。

现在,巨大的htmls和表单怎么办?这些东西应该如何划分?

探索不同的架构

将布局代码作为道具分开

  • 我喜欢顶层元素的类名与模块名相同的做法,这样在浏览器控制台调试时可以更好地查看。
  • 我喜欢这个模块对风格的要求。风格惯例很好,非常好的BEM格式。
require('./DefaultLayout.less');
var DefaultLayout = React.createClass({
    propTypes: {
        header: React.PropTypes.node,
        title: React.PropTypes.node,
        content: React.PropTypes.node
    },
    render: function(){
        return (
            <div className="DefaultLayout">
                <div className="DefaultLayout-header navbar navbar-default">
                    <div className="container">{this.props.header}</div>
                </div>div>
                // etc...
            </div>
        );
    }
});

独立的渲染组件。对大的渲染函数说 "不"。

render: function(){
    // ...
    return (
        <div className={classes}>
            <div className="Item-title">
                {this.renderTags()}
                {this.renderDate()}
            </div>
        </div>
    );
},
renderTags: function(){
    return (
        <div></div>
    );
},
renderDate: function(){
    return (
        <div></div>
    );
}