A Compact React Cookbook

前端之家收集整理的这篇文章主要介绍了A Compact React Cookbook前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这是一本非常 campact 的 React 煮书,收集了在实践 React 时的一些问题和解决方法

1Why not 2 way binding/为毛不用双向绑定

解释这个问题我们需要先看什么是双向绑定,什么是单向绑定

1.1双向绑定

也就是dom 上的 value 与 controller 或者 view controller 上的绑定,值保持一致。

1.2单向绑定

dom 上的值来源于 controller,但是 dom 上的值改变不会改变 controller 上的值。

1.3双向有什么不好1

  • perfomance
  • 我们真的需要吗?实际上有多少值是真的需要双向绑的
  • 到底谁动了我的值?too many sources of truth

1.4单向有什么好

  • 只有一个 source of truth,代码好 reason about
  • 更快
  • 需要的时候自己绑一把,也并不是多麻烦的事
var TwoWayBindingInput = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },handleChange: function(event) {
    this.setState({message: event.target.value}); // <= (setstate)
  },205)">render: message = this.state.message;
    return <input type="text" value={message} onChange={this.handleChange} />; <= (value)
  }
});

注意看这个双向绑定,第value行是单向绑定值messageinput元素上,第setstate行是把input元素的值绑定回来,但是注意看这里绑定回来需要通过setState来完成,这就保证了 React Component 的 source of truth 还是只有 state。

2What's Virtual DOM,why should we care / 为毛要用 Vitual Dom

2.1以前是如何操作 DOM 的 (Mutable)

@H_403_145@
  • query 到 DOM 上一个元素
  • 改吧改吧
  • 2.2Virtual DOM (Immutable)

    @H_403_145@
  • 想好要往 DOM 上放什么东西
  • 把它给 Virtual DOM
  • Virtual DOM 决定哪些应该修改 DOM 哪些不用

    为什么说前者是 Mutable 后者是 Immutable,这是相对你的业务逻辑来说的。

  • DOM 本身是 Mutable 的东西,把它柔和到你的业务上给你的逻辑加上了不少 mutable 的因素,而 Virtual DOM 成功的屏蔽掉了 mutable 的 DOM,每次 render 的 Component 其实都是新的,并不是以前 Component 的修改

    所以使用 Virutal DOM

    • 容易 reason about, 因为 immutable
    • 把紧耦合编程了高内聚
    @H_301_186@

    3Why Immutable / 为毛要不可变

    Immutable 是函数式的概念之一,一旦创建出来之后,就不能再改变。因此,当你想对其做修改,就得弄一个新的。

    好奇的同学要问了,但是 React 看起来是面向对象的啊。createClassstate函数式有状态和 class 吗?

    If a tree falls in a forest and no one is around to hear it,does it make a sound?2

    首先,函数式和面向对象并不冲突,两种编程范式分别有各自的方式解决问题。

    其次:

    3.1状态

    如果状态只存在于 Component 中又并没有影响任何人,它还是状态吗?

    ClojureScript 的 React 库 om,只有一个 app 级别的 state。因此所有的 component,其实并无状态。

    https://youtu.be/5yHFTN-_mOo

    3.2Class

    想象一下使用一个 React Component 的时候

    <AFancyHelloWord message="Good News Everyone!"/>
    

    来想象一下

    @H_403_145@
  • 尖括号<往右移
  • 尖括号变成圆括号
  • 里面再加个大括号
  • 等号变冒号
  • AFancyHelloWord({message:"Good News Everyone!"})
    

    ./images/futurama_August_26__2015_at_0617AM.gifok,如果把每个 Component 看成一个函数,为了我们的代码更好 reason about 而且更 loose couple,我们应该尽量要消除每一个 Component 的状态。 这样在 Component 的树中,我们可以随意切换 Component,以 Star Wars 为例,Anakin 有两样东西,Luke 和光剑:

    当 Anakin 变成 Darth Vader,光剑的颜色变红时,Darth Vadar 有 Luke 和 红色光剑。

    实际上我们需要尽量减少 Component 中的状态,而且对着少数的状态,由于他们是我们的 source of truth,并不希望他是 mutable 的,这样我很难知道谁动了我的 source of truth。

    3.3让你的数据结构 immutable 的工具们

    Immutablility helper

    这是 react addon 中自带的工具,如果你并不想完整的 Immutable 数据结构,这个工具可以帮助 copy 一份来做改动

    update = require('react-addons-update');
    inc = x=>x+1
    fancyPropsForChild=update(this.state,{
        x: {y: {z: {$set: 7}}},a: {b: {$push: [9]}},h: {$merge: {i: "j"}},e: {$apply: inc}
    });
    

    mori

    更为彻底的选择是,使用 ClojureScript 的 Immutable 数据结构。benchmark 要比 facebook 的 Immutable.js 好上许多,但是使用上跟 ClojureScript 一致, 用惯JavaScript的人可能不太能习惯,alternative 是使用我 fork 的 mori 版本conjs

    Immutable.js

    facebook 实现的 immutable 数据结构,使用上比较符合 JavaScript 习惯一些, 不过跑分低一些。

    4How to do Unit test React project / 如何单元测试

    4.1Jest

    总的来说,jest 的测试理念解决了非常多的前端测试的棘手问题,我做过一个关于 jest 的 session, 文章这里文章可能写得有点早,非常知道高兴的是终于支持最新的 nodejs 了,而且 重要的是 facebook 使用 jest 测试 react,有一些非常方便的 mock component 的方法

    recap 一下主要是

    • automock/ manual mock
    • jsdom
    • 并行测试

    4.2jasmine

    jasmine 只是一个引擎,jest 也是用 jasmine 作为引擎。但是如果由于某种原因你不想用 jest 的话,可能你需要花更多的 effort 在:

    • mock (rewire.js)
    • runner (karma)
    • headless browser for ci(phantomjs)

    所以并不推荐花这么大 effort 去撘一个 jasmine 的测试环境,关键还会有一系列的问题

    • phantomjs 怪怪的 issue
    • karma 复杂的配置
    • rewire 也有一些坑

    4.3mocha

    没试过用来测 React,不过 mocha 比 jasmine 好的一点是本身就可以跑在 node 上,使用 sinon(mock) 和 should.js(assert) 是个非常强大的一套测试工具。

    5Modular and Components

    5.1browserify

    简单的 modular bundler,推荐, 因为职责单一的工具更不容易遇到奇怪的问题。

    使用 browserify 使用babel transformer就可以把所有的 component 以 node 的方式模块化的组织,最后 bundle 成一个 js 文件

    5.2webpack

    以 grunt 的方式 browserify 你的代码,非常强大的 bundler。但是个人并不喜欢 grunt,karma,webpack 这种基于配置的工具,原因很简单,配置不是代码!配置不是代码!配置不是代码! 配对了当然简单,但是配错了怎么办,没法 debug。

    虽然不喜欢,我还是要告诉你怎么用,就这么一行配置就好了

    module: {
      loaders: [
        { test: /\.jsx?$/,exclude: /node_modules/,loader: "babel-loader"}
      ]
    }
    

    6How should I thinking in react way / 如何以 React 的方式解决问题

    要以 react 的方式思考,其实跟思考 HTML 差不多http://facebook.github.io/react/docs/thinking-in-react.html

    7What about Data Fetching / 只有 V 的话,数据 M 呢

    7.1justrest

    简单,rest 请求回来一个 Promise,你还可以用when获得更多的 promise 和 monad 用法

    无需 model 在 componentDidMount 发出 rest 请求,then 直接扔给 setState。最多 setState 前加些 map filter 把数据改改格式。

    7.2relay/graphql

    官方 data fetching 解决方案。

    比起由 component 去发请求,再转换数据格式。relay/graphql 的思想是有 component 定义数据形状,由 relay 去发请求,有 graphql server 跟去根据定义返回相应形状的数据。

    所以,对,会多一层 server layer。

    view 层简单了,graphql 要做的事情却不少。

    7.3falcor

    netflix 的简单版的 graphql可以参考我的todo falcor思想大致相似,但是更为简单一些,没有什么 QL,schema 之类的

    8What about Router / router 怎么办

    建议使用 isomorphic router,就是 browser 与 node 都可以用的 router

    8.1direactor

    非常轻量级的通用 router,并不是专门为 react 准备的,但是 router 而已,为毛要跟 component 耦合。

    client side

    routes = {
      '/author': ()=>React.render(<Author/>,domNode),'/author/:id': (id)=>React.render(<Auther id={id}/>,domNode)
    };
    router = Router(routes);
    router.init();
    

    server side

    只需要调用 router.dispatch 就好了,而且 server 端的 react 需要renderToString

    router = new director.http.Router({
      '/author': {
        get: function(){
          this.res.end(React.renderToString(<Author/>))
        }
      }
    });
    server = http.createServer(function (req,res) {
      router.dispatch(req,res,err) {
        res.writeHead(200,{ 'Content-Type': 'text/html' })
        if (err) {
          res.writeHead(404);
          res.end();
        }
      });
    });
    

    8.2react router

    非常非轻量级的 router,而且只能给 react component用。

    概念上就是使用 Route 把你的 Component 包起来,让 router 决定到底哪个 componet 上

    render((
      <Router>
        <Route path="/" component={App}>
          <Route path="about" component={About}/>
          <Route path="users" component={Users}>
            <Route path="/user/:userId" component={User}/>
          </Route>
          <Route path="*" component={NoMatch}/>
        </Route>
      </Router>
    ),document.body)
    

    9How to communicate between two components that don't have a parent-child relationship3/ 不是父子关系的 component 怎么交互

    对于这个问题,我的问题是

    如果不是父子关系或者兄弟或者伯父侄女,真的需要交互吗?

    如果是在同一颗树上,那么一定能找到一个共同的 parent,把 parent 的回调传进来就好了

    如果不在同一颗树上,你可能需要一个全局的一些东西

    9.1event

    使用随便一种 event emitter,比如backbon events。 在一个 componnet 中 trigger,另一个 component subscribe

    9.2flux

    flux 只是一个架构思想,你可以用任何自己喜欢的方式实现 其实跟 event emitter 差不多,只是针对和管理 state

    @H_301_654@ dispatcher

    作为action 的分发工作,决定哪些 action 引起哪些 store 的变化

    store

    状态与逻辑

    9.3router

    使用 router 传递信息也是可以的

    9.4应用级别 state

    跟 om 一样,全局应用级别 state

    10When should I use "key" / 什么时候该用 key

    只有当出现一串一样的元素的时候,这个时候 Virtual DOM 去 reconciliate(搞) DOM 的时候会傻傻分不清楚。

    别的时候不要用 key,key 已经出现在 virtual dom diff/reconciliation 的阶段,效率要更低于 shouldComponentUpdate,所以尽量通过 shouldComponentUpdate 来决定是否要 render component。

    官网文档的这个例子

    renderA: <div><span>first</span></div>
    renderB: <div><span>second</span><span>first</span></div>
    => [replaceAttribute textContent 'second'],[insertNode <span>first</span>]
    

    其实是往第一个位置插入了一个 span,但是会被 diff 成

    • 替换内容 first 到 second
    • 插入内容为 first 的 span

      不光是这样会更慢的问题,如果你在 first 上绑有事件的话,重新 render 后因为是 replace 了内容,因此这是原来的事件会变成 second 的事件,这样就完全错乱了。

    11What's these Warnings / 这些黄黄的是神马

    黄黄的东西(除了小黄人)请一定要除掉!

    所有 react 的 warning 描述都非常详细,请一定务必要除掉。

    12How to Profile Component Perfomance / 如何提升效率

    当然不是咖啡!

    12.2PureRenderMixin

    当你的 props 和 state 都是 immutable 的时候…

    PureRenderMixin = require('react-addons-pure-render-mixin');
    React.createClass({
      mixins: [PureRenderMixin],139)">return <div className={this.props.className}>foo</div>;
      }
    });
    

    12.3shouldComponentUpdate

    可以通过这个方法对于 component 到底什么情况下应该重新 render 调优

    所有图片来源于 giphy.com,copyright @Futurama

    Author: Jichao Ouyang

    Modified: 2015-11-16 Mon 00:39

    Generated by:Emacs24.5.1 (Orgmode 8.3.2)

    <Publish> with _(:з」∠)_ byOrgPress

    原文链接:https://www.f2er.com/react/307501.html

    猜你在找的React相关文章