React 生态圈介绍

by 张庆 2019-07-29

1. 设计架构

2. 常用库,框架

3. React的优缺点-我的见解

4. Mogul介绍

React架构

React Component API

提供组件API和生命周期

constructor,

render,

componentDidMount

componentWillUnmount

componentDidUpdate

shouldComponentUpdate

setState

.....

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

  tick() {
    this.setState(state => ({
      seconds: state.seconds + 1
    }));
  }

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

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

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

ReactDOM.render(
  <Timer />,
  document.getElementById('timer-example')
);

React Reconciler

虚拟dom算法, 设置统一处理逻辑, 告诉react 如何创建, 更新, 删除元素

Stack Reconciler (v15)

Fiber Reconciler (v16)

const Reconciler = require('react-reconciler');
 
const HostConfig = {
  // You'll need to implement some methods here.
  // See below for more information and examples.
};
 
const MyRenderer = Reconciler(HostConfig);
 
const RendererPublicAPI = {
  render(element, container, callback) {
    // Call MyRenderer.updateContainer() to schedule changes on the roots.
    // See ReactDOM, React Native, or React ART for practical examples.
  }
};
 
module.exports = RendererPublicAPI;

React Renderers

一个 renderer除了实现一些定义在React-Reconciler的方法,不做任何事情。 React-Reconciler 会执行这些定义的方法然后更新UI。如果你实现这些方法使用DOM API, 那么目标就是web。如果你实现这些使用IOS UI Kit API, 那么目标就是IOS。如果你实现这些方法使用Andorid UI API, 目标就是Android。实际上, 如何支持UI的系统都可以使用React。它不需要使用React去绘制

自定义renderer

import ReactReconciler from 'react-reconciler';

const rootHostContext = {};
const childHostContext = {};

const hostConfig = {
  now: Date.now,
  getRootHostContext: () => {
    return rootHostContext;
  },
  prepareForCommit: () => {},
  resetAfterCommit: () => {},
  getChildHostContext: () => {
    return childHostContext;
  },
  shouldSetTextContent: (type, props) => {
    return typeof props.children === 'string' || typeof props.children === 'number';
  },
  createInstance: (type, newProps, rootContainerInstance, _currentHostContext, workInProgress) => {
    const domElement = document.createElement(type);
    Object.keys(newProps).forEach(propName => {
      const propValue = newProps[propName];
      if (propName === 'children') {
        if (typeof propValue === 'string' || typeof propValue === 'number') {
          domElement.textContent = propValue;
        }
      } else if (propName === 'onClick') {
        domElement.addEventListener('click', propValue);
      } else if (propName === 'className') {
        domElement.setAttribute('class', propValue);
      } else {
        const propValue = newProps[propName];
        domElement.setAttribute(propName, propValue);
      }
    });
    return domElement;
  },
  createTextInstance: text => {
    return document.createTextNode(text);
  },
  appendInitialChild: (parent, child) => {
    parent.appendChild(child);
  },
  appendChild(parent, child) {
    parent.appendChild(child);
  },
  finalizeInitialChildren: (domElement, type, props) => {},
  supportsMutation: true,
  appendChildToContainer: (parent, child) => {
    parent.appendChild(child);
  },
  prepareUpdate(domElement, oldProps, newProps) {
    return true;
  },
  commitUpdate(domElement, updatePayload, type, oldProps, newProps) {
    Object.keys(newProps).forEach(propName => {
      const propValue = newProps[propName];
      if (propName === 'children') {
        if (typeof propValue === 'string' || typeof propValue === 'number') {
          domElement.textContent = propValue;
        }
      } else {
        const propValue = newProps[propName];
        domElement.setAttribute(propName, propValue);
      }
    });
  },
  commitTextUpdate(textInstance, oldText, newText) {
    textInstance.text = newText;
  },
  removeChild(parentInstance, child) {
    parentInstance.removeChild(child);
  }
};
const ReactReconcilerInst = ReactReconciler(hostConfig);
export default {
  render: (reactElement, domElement, callback) => {
    // Create a root Container if it doesnt exist
    if (!domElement._rootContainer) {
      domElement._rootContainer = ReactReconcilerInst.createContainer(domElement, false);
    }

    // update the root Container
    return ReactReconcilerInst.updateContainer(reactElement, domElement._rootContainer, null, callback);
  }
};

自定义renderer(2)

import React from 'react';
import ReactDOM from './myCustomRenderer';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <div className="App-intro">
          <div className="button-container">
            <button className="decrement-button" onClick={() => this.setState({ counter: this.state.counter - 1 })}>
              -
            </button>
            <span className="counter-text">{this.state.counter}</span>
            <button className="increment-button" onClick={() => this.setState({ counter: this.state.counter + 1 })}>
              +
            </button>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

JSX

JSX is a JavaScript render function that helps you insert your HTML right into your JavaScript code

const names = [‘John’, ‘Sarah’, ‘Kevin’, ‘Alice’];
const displayNewHires = (
  <ul>
    {names.map(name => <li>{name}</li> )}
  </ul>
);
ReactDOM.render(
  displayNewHires,
  document.getElementById(‘root’)
);
‘use strict’;
var names = [‘John’, ‘Sarah’, ‘Kevin’, ‘Alice’];
var displayNewHires = React.createElement(
  ‘ul’,
  null,
  names.map(function (name) {
    return React.createElement(
      ‘li’,
      null,
      name
    );
  })
);
ReactDOM.render(displayNewHires, document.getElementById(‘root’));

plugin-transform-react-jsx

React is Library

React 仅仅是一个库, 在具体使用中必须使用第三方库配合使用。

 

常用库和框架

Routing: react-router, reach

状态管理: redux, mobx, context+react-hooks

构建工具: create-react-app, gastby

框架: nextjs, relay

style: css-module(less, sass), css-in-js(radium),

styled-components, jss

如何挑选类库

主流, 流行

维护者

代码示例

宣传

如何挑选类库

安装他,做个简单个人demo

React 优点

Declarative(声明式): react 使用jsx, 数据驱动ui, 开发者无需关心如何新建,更新, 删除节点

组件化: react component api 定义了组件的完整生命周期,   可以构建复杂,高可用用户界面,也可以基于react封装现有组件,做到快速迁移。

Facebook背书, 最强大的社区,最前线的前端技术栈

灵活性: jsx只是针对用于界面的声明定义。

React 缺点

React is not Reactive: react状态数据非双向绑定, 且需要手动使用setState更新ui, 组件之间共享方法, 数据

选择综合征: react包含大量的插件库, 每一个依赖都有自己适用的场景, 需要使用者决定选择哪一个。

React 并不简单: react 只是开始。

谢谢

Made with Slides.com