函数式编程
- 一种编程范式,概念比较多
- 纯函数
- 不可变值
vdom和diff
同vue原理
http://wilberjiang.com/post/front/vue%E5%8E%9F%E7%90%86/
JSX本质
-
JSX等同于Vue模版
-
Vue模版不是html
-
JSX也不是JS
// JSX 基本用法
const imgElem = <div id="div1">
<p>some text</p>
<img src={imgUrl}/>
</div>
// JSX style
const styleData = { fontSize: '30px', color: 'blue' }
const styleElem = <p style={styleData}>设置 style</p>
// JSX 加载组件
const app = <div>
<Input submitTitle={onSubmitTitle}/>
<List list={list}/>
</div>
// JSX 事件
const eventList = <p onClick={this.clickHandler}>
some text
</p>
// JSX list
const listElem = <ul>{this.state.list.map((item, index) => {
return <li key={item.id}>index {index}; title {item.title}</li>
})}</ul>
// 总结
React.createElement('div', null, [child1, child2, child3])
React.createElement('div', {...}, child1, child2, child3)
React.createElement(List, null, child1, child2, '文本节点')
// h 函数
// 返回 vnode
// patch
- React.createElement即h函数,返回vnode
- 第一个参数,可能是组件,也可能是html tag
- 组件名,首字母必须大写(React规定)
合成事件
- 所有事件挂载到document上
- event不是原生的,是SyntheticEvent合成事件对象
- 和Vue事件不同,和DOM事件也不同
为何要合成事件机制
- 更好的兼容性和跨平台
- 挂载到document,减少内存消耗,避免频繁解绑
- 方便事件的统一管理(如事务机制)
setState、batchUpdate
- 有时异步(普通使用),有时同步(setTimeout、DOM事件)
- 有时合并(对象形式),有时不合并(函数形式)
核心要点
- setState主流程
- batchUpdate机制
- transaction(事务)机制
class ListDemo extends React.Component {
constructor(props) {}
render() {}
increase = () => {
// 开始:处于batchUpdate
// isBatchingUpdates = true
this.setState({
count: this.state.count + 1
})
// 结束
// isBatchingUpdates = false
}
}
class ListDemo extends React.Component {
constructor(props) {}
render() {}
increase = () => {
// 开始:处于batchUpdate
// isBatchingUpdates = true
setTimeout(() => {
// 此时isBatchingUpdates 是false
this.setState({
count: this.state.count + 1
})
})
// 结束
// isBatchingUpdates = false
}
}
能命中batchUpdate机制
- 生命周期(和它调用的函数)
- React中注册的事件(和它调用的函数)
- React可以“管理”的入口
不能命中batchUpdate机制
- setTimeout、setInterval等(和它调用的函数)
- 自定义的DOM事件(和它调用的函数)
- React“管不到”的入口
transaction事务机制
transaction.initialize = function () {
console.log("initialize")
}
transaction.close = function () {
console.log("close")
}
function method() {
console.log("abc")
}
transaction.perform(method)
// 输出“initialize”
// 输出“abc”
// 输出“close”
组件渲染/更新过程
渲染过程
- props state
- render()生成vnode
- patch(elm,vnode)
更新过程
- setState(newState)–>dirtyComponents(可能有子组件)
- render()生成newVnode
- patch(vnode,newVnode)
更新的两个阶段
上述的patch被拆分为两个阶段:
- reconciliation阶段-执行diff算法,纯JS计算
- commit阶段-将diff结果渲染DOM
可能会有性能问题:
- JS是单线程,且和DOM渲染共用一个线程
- 当组件足够复杂,组件更新时计算和渲染压力都大
- 同时再有DOM操作需求(动画、鼠标拖拽等),将卡顿
解决方案fiber:
- 将reconciliation阶段进行任务拆分(commit无法拆分)
- DOM需要渲染时暂停,空闲时恢复
- window.requestIdleCallback