11.getSnapshotBeforeUpdate源码实现
代码演化请观看视频,这里呈现相关代码:
js
// utils.js
export const deepClone = (data) => {
let type = getType(data);
let resultValue;
if (!(type === 'array' || type === 'object')) return data;
if (type === 'array') {
resultValue = [];
data.forEach((item) => {
resultValue.push(deepClone(item));
})
return resultValue;
} else if (type === 'object') {
resultValue = {};
for (const key in data) {
if (data.hasOwnProperty(key)) {
resultValue[key] = deepClone(data[key]);
}
}
return resultValue;
}
}
function getType(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
return map[toString.call(obj)];
}js
// Componet.js
import { deepClone } from './utils'
class Updater {
constructor(ClassComponentInstance){
this.ClassComponentInstance = ClassComponentInstance
this.pendingStates = []
}
addState(partialState){
this.pendingStates.push(partialState)
this.preHandleForUpdate()
}
preHandleForUpdate(){
if(updaterQueue.isBatch){
updaterQueue.updaters.add(this)
}else{
this.launchUpdate()
}
}
launchUpdate(nextProps){
const { ClassComponentInstance, pendingStates } = this
let prevProps = deepClone(this.ClassComponentInstance.props)///
let prevState = deepClone(this.ClassComponentInstance.state)///
if(pendingStates.length === 0 && !nextProps) return
let isShouldUpdate = true;
let nextState = this.pendingStates.reduce((preState, newState) => {
return {
...preState, ...newState
}
}, this.ClassComponentInstance.state);
if (ClassComponentInstance.shouldComponentUpdate && (!ClassComponentInstance.shouldComponentUpdate(nextProps, nextState))) {
isShouldUpdate = false;
}
this.pendingStates.length = 0
if(nextProps) ClassComponentInstance.props = nextProps
ClassComponentInstance.state = nextState
if(isShouldUpdate) ClassComponentInstance.update(prevProps, prevState) ///
}
}
export class Component {
static IS_CLASS_COMPONENT = true
constructor(props){
this.updater = new Updater(this)
this.state = {}
this.props = props
}
setState(partialState){
// // 1.合并属性
// this.state = {...this.state, ...partialState}
// // 2.重新渲染进行更新
// this.update()
this.updater.addState(partialState)
}
update(prevProps, prevState){///
// 1. 获取重新执行render函数后的虚拟DOM 新虚拟DOM
// 2. 根据新虚拟DOM生成新的真实DOM
// 3. 将真实DOM挂载到页面上
let oldVNode = this.oldVNode; // TODO: 让类组件拥有一个oldVNode属性保存类组件实例对应的的虚拟DOM
let oldDOM = findDomByVNode(oldVNode) // TODO: 将真实DOM保存到对应的虚拟DOM上
if (this.constructor.getDerivedStateFromProps) {
let newState = this.constructor.getDerivedStateFromProps(this.props, this.state) || {};
this.state = { ...this.state, ...newState };
}
let snapshot = this.getSnapshotBeforeUpdate && this.getSnapshotBeforeUpdate(prevProps, prevState);///
let newVNode = this.render()
updateDomTree(oldVNode, newVNode, oldDOM)
this.oldVNode = newVNode
if (this.componentDidUpdate) {
this.componentDidUpdate(this.props, this.state, snapshot);///
}
}
}