by 张庆 2019-07-29
1. 设计架构
2. 常用库,框架
3. React的优缺点-我的见解
4. Mogul介绍
提供组件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')
);
虚拟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;
一个 renderer除了实现一些定义在React-Reconciler的方法,不做任何事情。 React-Reconciler 会执行这些定义的方法然后更新UI。如果你实现这些方法使用DOM API, 那么目标就是web。如果你实现这些使用IOS UI Kit API, 那么目标就是IOS。如果你实现这些方法使用Andorid UI API, 目标就是Android。实际上, 如何支持UI的系统都可以使用React。它不需要使用React去绘制
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);
}
};
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 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 仅仅是一个库, 在具体使用中必须使用第三方库配合使用。
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
Declarative(声明式): react 使用jsx, 数据驱动ui, 开发者无需关心如何新建,更新, 删除节点
组件化: react component api 定义了组件的完整生命周期, 可以构建复杂,高可用用户界面,也可以基于react封装现有组件,做到快速迁移。
Facebook背书, 最强大的社区,最前线的前端技术栈
灵活性: jsx只是针对用于界面的声明定义。
React is not Reactive: react状态数据非双向绑定, 且需要手动使用setState更新ui, 组件之间共享方法, 数据
选择综合征: react包含大量的插件库, 每一个依赖都有自己适用的场景, 需要使用者决定选择哪一个。
React 并不简单: react 只是开始。
谢谢