《深入React技术栈》笔记

页面加载速度的改善

作为一名长期使用 React.js 的开发者,我对此问题有自己的答案和最佳实践,但你可能不一定完全同意.我对你的想法和观点很有兴趣,请留言以便讨论.

2.7 动画

TransitionGroup 能帮助我们快捷地识别出增加或删除的组件。

React Transition设计了以生命周期函数的方式来实现,即让子组件的每一个实例都实现相应地生命周期函数。当React Transition识别到某个子组件增或删时,则调用它相应地生命周期函数。我们可以再生命周期函数中实现动画逻辑。
如果每一个子组件的动效相同,那么每一个子组件可以共同用一个生命周期函数。因此React Transition 提供了 childFactory 配置,让用户自定义一个封装子组件的工厂方法,为子组件加上相应地生命周期函数。
React Transition提供的生命周期

  • componentWillAppear
  • componentDidAppear
  • componentWillEnter
  • componentDidEnter
  • componentWillLeave
  • componentDidLeave

componentWillxxx 只要在 componentWillReceiveProps中对this.props.childrennextProps.children做一个比较就可以了。componentDidxxx可以在componentWillxxx提供一个回调函数,用来执行componentDidxxx

React CSS Transition 为子组件的每个生命周期加了不同的className,这样用户可以很方便地根据 className 地变化来实现动画

<ReactCSSTransitionGroup
  transitionName="example"
  transitionEnterTimeout={400}
>
{items}
</ReactCSSTransitionGroup>

对应地css代码

.example-enter {
  transform: scaleY(0);
  &.example-enter-active {
    transform: scaleY(1);
    transition: transform .4s ease;
  }
}

使用react-motion实现一个spring开关

import React, {Component} from ''react;

class Switch extends Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);

    this.state = {
      open: false,
    }
  }
  handleClick() {
     this.setState({
      open: !this.state.open
    })
  }
  render() {
    return (
      <Motion style={{x: spring(this.state.open ? 400 : 0)}}>
          {({x}) =>
           <div className="demo">
             <div
               className="demo-block"
               onClick={this.handleClick}
               style={{
                 transform: `translate3d(${x}px, 0, 0)`,
          }}
 />
 </div>
 } 
      </Motion>
    )
  }
}

技术选型

这次项目的技术选择时,遵循了尽可能采用当前当前市场上已经存在的普遍使用的技术这一原则。暗号就是:「活脱脱像范例应用一样Start」。这样一来,无论是谁都可以轻松的获取到相应的文档等信息,同时其它的团队和公司如果要参与到项目中来也能很快的上手。然而在真正进行开发的时候,一些细节实现上因为各种各样的原因存在一些例外的情况,但是在极大程度上保持了各个模块的独立性。最终系统的大体构成如下图所示:

 图片 1

z-bigpicture.png

(有些地方做了省略)

1. 扁平化 state

API 经常会返回嵌套的资源.这在 Flux 或基于 Redux 的架构中处理起来会非常困难.我们推荐使用normalizr这类库将数据进行扁平化处理,尽可能地扁平化state.

像这样:

const data = normalize(response, arrayOf(schema.user))

state = _.merge(state, data.entities)

(我们使用isomorphic-fetch与API进行通信)

一、初入React世界

不再「咯噔」

系统重构之前的Ameblo由于存在一些高度没有固定的模块,出现了「咯噔」现象。这种「咯噔」会导致误点击以及页面的重绘,十分令人厌烦。而此模块高度固定也做为本次系统重构的UI设计的前提。特别是页面间导航作为十分重要的元素,我们经过努力使得在页面跳转时每次都可以触击到相同的位置。

图片 2

z-gatan.gif

「咯噔」的一个例子。点击[次のページ](下一页)的时候,额外的元素由于加载缓慢,造成误点击。

 图片 3

z-paging-fixed.gif

系统重构之后,元素的位置被固定下来,减轻了页面跳转时给用户心理上带来的负担。

根据我们的经验,Flux 经常被过度使用,(就是大家总是在不需要它的时候仍然用了它).

5.2 Redux middleware

Redux 提供了 applyMiddleware 方法来加载 middleware,其源码如下

import compose from './compose';

export default function applyMiddleware(...middlewares) {
  return (next) => (reducer, initialState) => {
    // 获取得到原始的store
    let store = next(reducer, initialState);
    let dispatch = store.dispatch;
    // 赋值一个空数组,用来存储后新的dispatch分裂函数
    let chain = [];

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
     };

    chain = middlewares.map(middleware => middleware(middlewareAPI));
    // 将分裂的函数组合每次都会执行,即每次都执行这些中间件函数
    dispatch = compose(...chain)(store.dispatch);

    return {
      ...store,
      dispath
    }
  }
}

middleware运行原理

  1. 函数式编程思想设计
    通过函数式编程中的 currying。currying 的middleware结构的好处有以下两点
  • 易串联:不断currying形成的middleware可以累积参数,再配合组合方式,很容易形成 pipeline来处理数据流
  • 共享store:applyMiddleware执行过程中,store还是旧的,applyMiddleware完成后,所有的middleware内部拿到的sotore都是最新且相同的
  1. 给middleware分发store
    let newStore = applyMiddleware(mid1, mid2, mid3)(createStore)(reducer, null);

  2. 组合串联middleware
    dispatch = compose(...chain)(store.dispatch)
    Redux中compose的实现

function compose(...funs) {
  return arg => funs.reduceRight((composed, f) => f((composed), arg))
}

compose(...funcs) 返回的是一个匿名函数,其中 funcs 就是 chain 数组。当调用 reduceRight
时,依次从 funcs 数组的右端取一个函数 fx 拿来执行,fx 的参数 composed 就是前一次 fx 1 执
行的结果,而第一次执行的 fn(n 代表 chain 的长度)的参数 arg 就是 store.dispatch。

  1. 在 middleware 中调用 dispatch 会发生什么

图片 4

Redux middleware流程图.png

如果这个middleware粗暴的调用 store.dispatch(acton),就会形成无线循环了。
这里我们就用到了Redux Thunk。
Redux Thunk 会判断 action 是否是函数。如果是,则执行 action,否则继续传递 action 到下一个 middleware。

const tuhun = store => next => action => {
  typeof action === 'function' ?
    action(store.dispatch, store.getState) :
    next(action)
}

写在最后

这次系统重构的出发点是对技术的挑战,结果获得了良好的用户反馈,并对业务作出了贡献,我们自身也感到非常有价值,获得了极大的成就感。采用最新迎合时代潮流的技术自然提升服务的质量,也使得这种文化在公司在生根。在此,对及早导入Isomorphic JavaScript,并向日本国内推广的同事 @ahomu 表示感谢!

本文由上海时时乐走势图发布于web前端,转载请注明出处:《深入React技术栈》笔记

您可能还会对下面的文章感兴趣: