Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[框架] React 动态/精要/生态/源码 #12

Open
BlackGanglion opened this issue Apr 3, 2017 · 7 comments
Open

[框架] React 动态/精要/生态/源码 #12

BlackGanglion opened this issue Apr 3, 2017 · 7 comments

Comments

@BlackGanglion
Copy link
Owner

BlackGanglion commented Apr 3, 2017

参考书籍:
深入react 技术栈

2017年 React 会议
https://facebook.github.io/react/community/conferences.html

从零到一的 React 学习与实践资料索引
https://zhuanlan.zhihu.com/p/26877549

@BlackGanglion BlackGanglion changed the title [框架] React 最新动态与精要 [框架] React 动态/精要/生态/源码 Apr 3, 2017
@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 5, 2017

react-bits 一本关于 React 设计模式、技术与技巧的书,涵盖了常见的 React 应用开发中的设计模式、需要规避的反模式、处理 UX 变种、性能调试与样式处理等等。

注:反模式(anti-pattern)指的是在实践中明显出现但又低效或是有待优化的设计模式

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 6, 2017

setState

React 源码剖析系列 - 解密 setState
setState:这个API设计到底怎么样

setState 可以传入一个回调,在 setSate 完成后触发

ReactComponent.prototype.setState = function(partialState, callback)

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 10, 2017

从 ES6 到 ES5

// ES6
class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {secondsElapsed: 0};
  }

  tick() {
    this.setState((prevState) => ({
      secondsElapsed: prevState.secondsElapsed + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
      <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
    );
  }
}

ReactDOM.render(<Timer />, mountNode);

// babel ES5
"use strict";

var _createClass = function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor)
        descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
}();

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
  });
  if (superClass)
    Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var Timer = function (_React$Component) {
  _inherits(Timer, _React$Component);

  function Timer(props) {
    _classCallCheck(this, Timer);

    var _this = _possibleConstructorReturn(this, (Timer.__proto__ || Object.getPrototypeOf(Timer)).call(this, props));

    _this.state = { secondsElapsed: 0 };
    return _this;
  }

  _createClass(Timer, [{
    key: "tick",
    value: function tick() {
      this.setState(function (prevState) {
        return {
          secondsElapsed: prevState.secondsElapsed + 1
        };
      });
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;

      this.interval = setInterval(function () {
        return _this2.tick();
      }, 1000);
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      clearInterval(this.interval);
    }
  }, {
    key: "render",
    value: function render() {
      return React.createElement("div", null, "Seconds Elapsed: ", this.state.secondsElapsed);
    }
  }]);

  return Timer;
}(React.Component);

ReactDOM.render(React.createElement(Timer, null), mountNode);

基础源码

ReactElement.createElement = function(type, config, children)

主要是设置 ref,设置key,合成 props(children、defaultProps),返回 ReactElement 对象

ReactDOM.render = function(nextElement, container, callback)

返回 renderSubtreeIntoContainer(null, element, container, callback) 的执行结果,element 支持 ReactNodeList,可传入组件数组

Fiber

DOMRenderer 由 ReactFiberReconciler 生成,传入 ReactFiberReconciler 的 config 将交给 ReactFiberScheduler 处理。

  1. ReactFiberHostContext,提取 config 中的 getChildHostContext 与 getRootHostContext,对接 ReactFiberStack,返回 HostContext 的一系列方法
  2. ReactFiberBeginWork,

DOMRenderer.createContainer(container),利用根节点创建容器,createFiberRoot(container)
首先 createHostRootFiber(),基于 createFiber,返回 fiber 对象

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 27, 2017

React 的合成事件机制
为何在编写事件函数时需要指定this?
React 中 this 是指向组件本身的,this.*** 后上下文发生改变,即 this 也发生了改变

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 29, 2017

Things nobody will tell you about React.js

  • good code means also better product quality
  • npm 包太多,对初学者不友好,状态管理redux与mobx的选择,脚手架搭建困难
  • mobx 需要使用 ES2017 decorator,导致 eslint 无法工作,需要使用 babel-eslint
  • mobx 无法避免不期望的更新,可以对 store 直接修改,store.message = ‘hello’,类vue
  • Redux 核心概念过于复杂,代码增长过快,需要使用一些第三方库简化
  • React-Router 更新过快,且不兼容,上手困难,React.children.only 导致必须额外包裹一层 div

dan_abramov 的回复

  • React 16 向后兼容,具有相同的API(主要是底层使用Fiber)
  • 开始可以使用 react 内置的 state,在需要时再考虑 redux 与 mobx
  • React 16 render 将支持 array,不需要再额外包裹
  • 清晰的数据流动与避免DOM操作,使应用更加稳定
  • 所有文件均需要 import react,是因为 JSX,在作用域内引入 react,使得 JSX 能与浏览器的全局变量一起工作

project-need-react

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented May 3, 2017

react-fiber-architecture 中四篇文章

React Components, Elements, and Instances

传统面向对象的 UI 编程中,痛点是需要管理实例
在没有 React 的日子里,我们需要去保留 DOM 与子组件的引用,手动得进行创建,更新,销毁。

在 React 中,组件元素与 DOM 元素可相互混合嵌套,定义 type,props(children、color...),React 屏蔽开发者对于底层 DOM 的操作,完全由框架本身来完成,而 type、props、children 的层层嵌套又转而用JSX 来表达,降低开发者的成本。

在 React 中,更多是做组件的声明,而不需要实例化,因为 React 已经帮你完成了。函数返回的组件没有示例

Reconciliation

React 将一颗树转换为另一颗树的算法简化,基于以下两个前提将 O(n^3) 转换为 O(n):

  • 不同类型的两个元素将会产生不同的树
  • 开发人员可以使用一个 key prop 来指示在不同的渲染中那个那些元素可以保持稳定(key 的作用)

diff 算法

  • 不同类型的元素,会销毁原来的树构建新的树,所有子孙节点都会被卸载重建
  • DOM 元素类型相同,如果仅仅是className/style 的修改,会只修改相应的
  • 组件类型相同,组件实例保持不变,而是调用 componentWillReceiveProps componentWillUpdate
  • 子组件递归,尾部添加效率高,头部添加,无法获知后面是否改变(没有 key)
  • key,当子节点有了 key ,React 使用这个 key 去比较原来的树的子节点和之后树的子节点,使头部添加高效

React - Basic Theoretical Concepts
翻译:React 设计思想

design-principles

@BlackGanglion
Copy link
Owner Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant