Match-id-87d7a306856b74030f13b40cb209b873d055d41e

This commit is contained in:
* 2022-01-25 11:37:51 +08:00 committed by *
parent fa55d306c2
commit 2d97a19610
15 changed files with 297 additions and 296 deletions

View File

@ -10,30 +10,6 @@ import {findDOMByClassInst} from '../renderer/vnode/VNodeUtils';
import {TreeRoot} from '../renderer/vnode/VNodeTags';
import {Callback} from '../renderer/UpdateHandler';
function executeRender(
children: any,
container: Container,
callback?: Callback,
) {
let treeRoot = container._treeRoot;
if (!treeRoot) {
treeRoot = createRoot(children, container, callback);
} else { // container被render过
if (typeof callback === 'function') {
const cb = callback;
callback = function () {
const instance = getFirstCustomDom(treeRoot);
cb.call(instance);
};
}
// 执行更新操作
startUpdate(children, treeRoot, callback);
}
return getFirstCustomDom(treeRoot);
}
function createRoot(children: any, container: Container, callback?: Callback) {
// 清空容器
let child = container.lastChild;
@ -66,8 +42,32 @@ function createRoot(children: any, container: Container, callback?: Callback) {
return treeRoot;
}
function executeRender(
children: any,
container: Container,
callback?: Callback,
) {
let treeRoot = container._treeRoot;
if (!treeRoot) {
treeRoot = createRoot(children, container, callback);
} else { // container被render过
if (typeof callback === 'function') {
const cb = callback;
callback = function () {
const instance = getFirstCustomDom(treeRoot);
cb.call(instance);
};
}
// 执行更新操作
startUpdate(children, treeRoot, callback);
}
return getFirstCustomDom(treeRoot);
}
function findDOMNode(domOrEle: Element): null | Element | Text {
if (domOrEle == null) {
if (!domOrEle) {
return null;
}

View File

@ -72,7 +72,7 @@ export function getNearestVNode(dom: Node): null | VNode {
}
// 获取 vNode 上的属性相关信息
export function getVNodeProps(dom: Element | Text): Props {
export function getVNodeProps(dom: Element | Text): Props | null{
return dom[internalKeys.props] || null;
}
@ -93,7 +93,8 @@ export function getEventListeners(dom: EventTarget): Set<string> {
export function getEventToListenerMap(target: EventTarget): Map<string, EventListener> {
let eventsMap = target[internalKeys.nonDelegatedEvents];
if (!eventsMap) {
eventsMap = target[internalKeys.nonDelegatedEvents] = new Map();
eventsMap = new Map();
target[internalKeys.nonDelegatedEvents] = new Map();
}
return eventsMap;
}

View File

@ -55,13 +55,7 @@ function getChildNS(parentNS: string | null, tagName: string): string {
// 获取容器
export function getNSCtx(dom: Container, parentNS: string, type: string): string {
let namespace;
if (dom) {
namespace = getChildNS(dom.namespaceURI ?? null, dom.nodeName);
} else {
namespace = getChildNS(parentNS, type);
}
return namespace;
return dom ? getChildNS(dom.namespaceURI ?? null, dom.nodeName) : getChildNS(parentNS, type);
}
export function prepareForSubmit(): void {
@ -156,7 +150,7 @@ export function newTextDom(
// 提交vNode的类型为Component或者Text的更新
export function submitDomUpdate(tag: string, vNode: VNode) {
const newProps = vNode.props;
const element: Element = vNode.realNode;
const element: Element | null = vNode.realNode;
if (tag === DomComponent) {
// DomComponent类型
@ -179,10 +173,12 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
}
}
} else if (tag === DomText) {
if (element != null) {
// text类型
element.textContent = newProps;
}
}
}
export function clearText(dom: Element): void {
dom.innerHTML = '';

View File

@ -8,6 +8,27 @@ import {
} from '../../event/EventBinding';
import { isEventProp, isNativeElement } from '../validators/ValidateProps';
function updateOneProp(dom, propName, propVal, isNativeTag, isInit?: boolean) {
if (propName === 'style') {
setStyles(dom, propVal);
} else if (propName === 'dangerouslySetInnerHTML') {
dom.innerHTML = propVal.__html;
} else if (propName === 'children') { // 只处理纯文本子节点其他children在VNode树中处理
if (typeof propVal === 'string' || typeof propVal === 'number') {
dom.textContent = String(propVal);
}
} else if (isEventProp(propName)) {
// 事件监听属性处理
if (!allDelegatedHorizonEvents.has(propName)) {
listenNonDelegatedEvent(propName, dom, propVal);
}
} else {
if (!isInit || (isInit && propVal != null)) {
updateCommonProp(dom, propName, propVal, isNativeTag);
}
}
}
// 初始化DOM属性
export function setDomProps(
tagName: string,
@ -38,27 +59,6 @@ export function updateDomProps(
}
}
function updateOneProp(dom, propName, propVal, isNativeTag, isInit?: boolean) {
if (propName === 'style') {
setStyles(dom, propVal);
} else if (propName === 'dangerouslySetInnerHTML') {
dom.innerHTML = propVal.__html;
} else if (propName === 'children') { // 只处理纯文本子节点其他children在VNode树中处理
if (typeof propVal === 'string' || typeof propVal === 'number') {
dom.textContent = String(propVal);
}
} else if (isEventProp(propName)) {
// 事件监听属性处理
if (!allDelegatedHorizonEvents.has(propName)) {
listenNonDelegatedEvent(propName, dom, propVal);
}
} else {
if (!isInit || (isInit && propVal != null)) {
updateCommonProp(dom, propName, propVal, isNativeTag);
}
}
}
// 找出两个 DOM 属性的差别,生成需要更新的属性集合
export function compareProps(
oldProps: Object,

View File

@ -122,7 +122,9 @@ function getProcessListenersFacade(
));
}
if (nativeEvtName === 'compositionend' || nativeEvtName === 'compositionstart' || nativeEvtName === 'compositionupdate') {
if (nativeEvtName === 'compositionend' ||
nativeEvtName === 'compositionstart' ||
nativeEvtName === 'compositionupdate') {
processingListenerList = processingListenerList.concat(getCompositionListeners(
nativeEvtName,
nativeEvent,
@ -183,13 +185,14 @@ export function handleEventMain(
// 有事件正在执行,同步执行事件
if (isInEventsExecution) {
return triggerHorizonEvents(nativeEvtName, isCapture, nativeEvent, rootVNode);
triggerHorizonEvents(nativeEvtName, isCapture, nativeEvent, rootVNode);
return;
}
// 没有事件在执行,经过调度再执行事件
isInEventsExecution = true;
try {
return asyncUpdates(() =>
asyncUpdates(() =>
triggerHorizonEvents(
nativeEvtName,
isCapture,

View File

@ -5,15 +5,6 @@ import {handleEventMain} from './HorizonEventMain';
import {runDiscreteUpdates} from '../renderer/Renderer';
import {getEventTarget} from './utils';
// 生成委托事件的监听方法
export function createCustomEventListener(
target: EventTarget,
nativeEvtName: string,
isCapture: boolean,
): EventListener {
return triggerDelegatedEvent.bind(null, nativeEvtName, isCapture, target);
}
// 触发委托事件
function triggerDelegatedEvent(
nativeEvtName: string,
@ -39,3 +30,12 @@ function triggerDelegatedEvent(
}
handleEventMain(nativeEvtName, isCapture, nativeEvent, targetVNode, targetDom);
}
// 生成委托事件的监听方法
export function createCustomEventListener(
target: EventTarget,
nativeEvtName: string,
isCapture: boolean,
): EventListener {
return triggerDelegatedEvent.bind(null, nativeEvtName, isCapture, target);
}

View File

@ -4,6 +4,48 @@
import {VNode} from '../../renderer/Types';
// 从原生事件中复制属性到自定义事件中
function extendAttribute(target, source) {
const attributes = [
// AnimationEvent
'animationName', 'elapsedTime', 'pseudoElement',
// CompositionEvent、InputEvent
'data',
// DragEvent
'dataTransfer',
// FocusEvent
'relatedTarget',
// KeyboardEvent
'key', 'keyCode', 'charCode', 'code', 'location', 'ctrlKey', 'shiftKey',
'altKey', 'metaKey', 'repeat', 'locale', 'getModifierState', 'clipboardData',
// MouseEvent
'button', 'buttons', 'clientX', 'clientY', 'movementX', 'movementY',
'pageX', 'pageY', 'screenX', 'screenY', 'currentTarget',
// PointerEvent
'pointerId', 'width', 'height', 'pressure', 'tangentialPressure',
'tiltX', 'tiltY', 'twist', 'pointerType', 'isPrimary',
// TouchEvent
'touches', 'targetTouches', 'changedTouches',
// TransitionEvent
'propertyName',
// UIEvent
'view', 'detail',
// WheelEvent
'deltaX', 'deltaY', 'deltaZ', 'deltaMode',
];
attributes.forEach(attr => {
if (typeof source[attr] !== 'undefined') {
if (typeof source[attr] === 'function') {
target[attr] = function() {
return source[attr].apply(source, arguments);
};
} else {
target[attr] = source[attr];
}
}
})
}
export class CustomBaseEvent {
data: string;
@ -79,46 +121,3 @@ export class CustomBaseEvent {
this.isPropagationStopped = () => true;
}
}
// 从原生事件中复制属性到自定义事件中
function extendAttribute(target, source) {
const attributes = [
// AnimationEvent
'animationName', 'elapsedTime', 'pseudoElement',
// CompositionEvent、InputEvent
'data',
// DragEvent
'dataTransfer',
// FocusEvent
'relatedTarget',
// KeyboardEvent
'key', 'keyCode', 'charCode', 'code', 'location', 'ctrlKey', 'shiftKey',
'altKey', 'metaKey', 'repeat', 'locale', 'getModifierState', 'clipboardData',
// MouseEvent
'button', 'buttons', 'clientX', 'clientY', 'movementX', 'movementY',
'pageX', 'pageY', 'screenX', 'screenY', 'currentTarget',
// PointerEvent
'pointerId', 'width', 'height', 'pressure', 'tangentialPressure',
'tiltX', 'tiltY', 'twist', 'pointerType', 'isPrimary',
// TouchEvent
'touches', 'targetTouches', 'changedTouches',
// TransitionEvent
'propertyName',
// UIEvent
'view', 'detail',
// WheelEvent
'deltaX', 'deltaY', 'deltaZ', 'deltaMode',
];
attributes.forEach(attr => {
if (typeof source[attr] !== 'undefined') {
if (typeof source[attr] === 'function') {
target[attr] = function() {
return source[attr].apply(source, arguments);
};
} else {
target[attr] = source[attr];
}
}
})
}

View File

@ -72,7 +72,7 @@ export class CustomKeyboardEvent extends CustomBaseEvent {
super(customEvtName, nativeEvtName, nativeEvt, vNode, target);
this.key = getKey(nativeEvt);
this.charCode = nativeEvtName === 'keypress' ? uniqueCharCode(nativeEvt) : 0;
this.keyCode = (nativeEvtName === 'keydown' || nativeEvtName === 'keyup') ? nativeEvt.keyCode : 0;
this.keyCode = nativeEvtName === 'keydown' || nativeEvtName === 'keyup' ? nativeEvt.keyCode : 0;
this.which = this.charCode || this.keyCode;
}
}

View File

@ -9,7 +9,7 @@ const SPACE_CHAR = String.fromCharCode(CHAR_CODE_SPACE);
function getInputCharsByNative(
eventName: string,
nativeEvent: any,
): string | void {
): string | null | void {
if (eventName === 'compositionend') {
return (nativeEvent.detail && nativeEvent.detail.data) || null;
}

View File

@ -13,7 +13,7 @@ const horizonEventName = 'onSelect'
let currentElement = null;
let currentVNode = null;
let lastSelection = null;
let lastSelection: Selection | null = null;
function initTargetCache(dom, vNode) {
if (isTextInputElement(dom) || dom.contentEditable === 'true') {
@ -85,7 +85,7 @@ export function getListeners(
target: null | EventTarget,
): ProcessingListenerList {
const targetNode = vNode ? getDom(vNode) : window;
let eventUnitList = [];
let eventUnitList: ProcessingListenerList = [];
switch (name) {
case 'focusin':
initTargetCache(targetNode, vNode);

View File

@ -10,7 +10,18 @@ import {
cacheOldCtx,
} from '../components/context/CompatibleContext';
export function captureRender(processing: VNode): Array<VNode> | null {
function captureIncompleteClassComponent(processing, Component, nextProps) {
processing.tag = ClassComponent;
const hasOldContext = isOldProvider(Component);
cacheOldCtx(processing, hasOldContext);
resetDepContexts(processing);
return getIncompleteClassComponent(Component, processing, nextProps);
}
export function captureRender(processing: VNode): VNode | null {
const Component = processing.type;
const unresolvedProps = processing.props;
const resolvedProps =
@ -28,14 +39,3 @@ export function bubbleRender(processing: VNode) {
resetOldCtx(processing);
}
}
function captureIncompleteClassComponent(processing, Component, nextProps) {
processing.tag = ClassComponent;
const hasOldContext = isOldProvider(Component);
cacheOldCtx(processing, hasOldContext);
resetDepContexts(processing);
return getIncompleteClassComponent(Component, processing, nextProps);
}

View File

@ -13,10 +13,6 @@ import { captureFunctionComponent } from './FunctionComponent';
import { captureClassComponent } from './ClassComponent';
import { captureMemoComponent } from './MemoComponent';
export function captureRender(processing: VNode, shouldUpdate: boolean): VNode | null {
return captureLazyComponent(processing, processing.type, shouldUpdate);
}
export function bubbleRender() { }
const LazyRendererMap = {
@ -26,6 +22,20 @@ const LazyRendererMap = {
[MemoComponent]: captureMemoComponent,
};
export function mergeDefaultProps(Component: any, props: object): object {
if (Component && Component.defaultProps) {
const clonedProps = { ...props };
const defaultProps = Component.defaultProps;
Object.keys(defaultProps).forEach(key => {
if (clonedProps[key] === undefined) {
clonedProps[key] = defaultProps[key];
}
});
return clonedProps;
}
return props;
}
function captureLazyComponent(
processing,
lazyComponent,
@ -43,7 +53,8 @@ function captureLazyComponent(
// 加载得到的Component存在type中
processing.type = Component;
const lazyVNodeTag = processing.tag = getLazyVNodeTag(Component);
const lazyVNodeTag = getLazyVNodeTag(Component);
processing.tag = getLazyVNodeTag(Component);
const lazyVNodeProps = mergeDefaultProps(Component, processing.props);
const lazyRender = LazyRendererMap[lazyVNodeTag];
@ -68,16 +79,6 @@ function captureLazyComponent(
}
}
export function mergeDefaultProps(Component: any, props: object): object {
if (Component && Component.defaultProps) {
const clonedProps = { ...props };
const defaultProps = Component.defaultProps;
Object.keys(defaultProps).forEach(key => {
if (clonedProps[key] === undefined) {
clonedProps[key] = defaultProps[key];
}
});
return clonedProps;
}
return props;
export function captureRender(processing: VNode, shouldUpdate: boolean): VNode | null {
return captureLazyComponent(processing, processing.type, shouldUpdate);
}

View File

@ -19,107 +19,6 @@ export enum SuspenseChildStatus {
ShowFallback = 'showFallback',
}
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | VNode | null {
if (
!processing.isCreated &&
processing.oldProps === processing.props &&
!getContextChangeCtx() &&
!shouldUpdate
) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback) {
// 当显示fallback时suspense的子组件要更新
return updateFallback(processing);
}
return onlyUpdateChildVNodes(processing);
}
return captureSuspenseComponent(processing);
}
function updateFallback(processing: VNode): Array<VNode> | VNode | null {
const childFragment: VNode = processing.child;
if (childFragment.childShouldUpdate) {
if (processing.promiseResolve) {
// promise已完成展示promise返回的新节点
return captureSuspenseComponent(processing);
} else {
// promise未完成继续显示fallback不需要继续刷新子节点
const fallbackFragment: VNode = processing.child.next;
childFragment.childShouldUpdate = false;
fallbackFragment.childShouldUpdate = false;
return null;
}
} else {
const children = onlyUpdateChildVNodes(processing);
if (children !== null) {
// child不需要更新跳过child处理fallback
return children[1];
} else {
return null;
}
}
}
export function bubbleRender(processing: VNode) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback
|| (!processing.isCreated && processing.oldSuspenseChildStatus === SuspenseChildStatus.ShowFallback)
) {
FlagUtils.markUpdate(processing);
}
return null;
}
export function captureSuspenseComponent(processing: VNode) {
const nextProps = processing.props;
// suspense被捕获后需要展示fallback
const showFallback = processing.suspenseDidCapture;
if (showFallback) {
processing.suspenseDidCapture = false;
const nextFallbackChildren = nextProps.fallback;
return createFallback(processing, nextFallbackChildren);
} else {
const newChildren = nextProps.children;
return createSuspenseChildren(processing, newChildren);
}
}
// 创建子节点
function createSuspenseChildren(processing: VNode, newChildren) {
let childFragment: VNode;
if (!processing.isCreated) {
const oldChildFragment: VNode = processing.child;
const oldFallbackFragment: VNode | null = oldChildFragment.next;
childFragment = updateVNode(oldChildFragment);
childFragment.next = null;
// 将Suspense新的子参数传给子Fragment
childFragment.props = processing.props.children;
childFragment.shouldUpdate = true;
// 删除fallback
if (oldFallbackFragment !== null) {
FlagUtils.setDeletion(oldFallbackFragment);
processing.dirtyNodes = [oldFallbackFragment];
}
// SuspenseComponent 中使用
processing.suspenseChildStatus = SuspenseChildStatus.ShowChild;
} else {
childFragment = createVNode(Fragment, null, newChildren);
}
childFragment.parent = processing;
childFragment.cIndex = 0;
updateVNodePath(childFragment);
processing.child = childFragment;
processing.promiseResolve = false;
return processing.child;
}
// 创建fallback子节点
function createFallback(processing: VNode, fallbackChildren) {
const childFragment: VNode = processing.child;
@ -152,13 +51,118 @@ function createFallback(processing: VNode, fallbackChildren) {
return fallbackFragment;
}
// 创建子节点
function createSuspenseChildren(processing: VNode, newChildren) {
let childFragment: VNode;
if (!processing.isCreated) {
const oldChildFragment: VNode = processing.child;
const oldFallbackFragment: VNode | null = oldChildFragment.next;
childFragment = updateVNode(oldChildFragment);
childFragment.next = null;
// 将Suspense新的子参数传给子Fragment
childFragment.props = processing.props.children;
childFragment.shouldUpdate = true;
// 删除fallback
if (oldFallbackFragment !== null) {
FlagUtils.setDeletion(oldFallbackFragment);
processing.dirtyNodes = [oldFallbackFragment];
}
// SuspenseComponent 中使用
processing.suspenseChildStatus = SuspenseChildStatus.ShowChild;
} else {
childFragment = createVNode(Fragment, null, newChildren);
}
childFragment.parent = processing;
childFragment.cIndex = 0;
updateVNodePath(childFragment);
processing.child = childFragment;
processing.promiseResolve = false;
return processing.child;
}
export function captureSuspenseComponent(processing: VNode) {
const nextProps = processing.props;
// suspense被捕获后需要展示fallback
const showFallback = processing.suspenseDidCapture;
if (showFallback) {
processing.suspenseDidCapture = false;
const nextFallbackChildren = nextProps.fallback;
return createFallback(processing, nextFallbackChildren);
} else {
const newChildren = nextProps.children;
return createSuspenseChildren(processing, newChildren);
}
}
function updateFallback(processing: VNode): Array<VNode> | VNode | null {
const childFragment: VNode | null= processing.child;
if (childFragment?.childShouldUpdate) {
if (processing.promiseResolve) {
// promise已完成展示promise返回的新节点
return captureSuspenseComponent(processing);
} else {
// promise未完成继续显示fallback不需要继续刷新子节点
const fallbackFragment: VNode = processing.child.next;
childFragment.childShouldUpdate = false;
fallbackFragment.childShouldUpdate = false;
return null;
}
} else {
const children = onlyUpdateChildVNodes(processing);
if (children !== null) {
// child不需要更新跳过child处理fallback
return children[1];
} else {
return null;
}
}
}
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | VNode | null {
if (
!processing.isCreated &&
processing.oldProps === processing.props &&
!getContextChangeCtx() &&
!shouldUpdate
) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback) {
// 当显示fallback时suspense的子组件要更新
return updateFallback(processing);
}
return onlyUpdateChildVNodes(processing);
}
return captureSuspenseComponent(processing);
}
export function bubbleRender(processing: VNode) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback
|| (!processing.isCreated && processing.oldSuspenseChildStatus === SuspenseChildStatus.ShowFallback)
) {
FlagUtils.markUpdate(processing);
}
return null;
}
function canCapturePromise(vNode: VNode | null): boolean {
return vNode?.suspenseChildStatus !== SuspenseChildStatus.ShowFallback && vNode?.props.fallback !== undefined;
}
// 处理Suspense子组件抛出的promise
export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, error: any): boolean {
export function handleSuspenseChildThrowError(parent: VNode | null, processing: VNode, error: any): boolean {
let vNode = parent;
// 向上找到最近的不在fallback状态的Suspense并触发重新渲染
do {
if (vNode.tag === SuspenseComponent && canCapturePromise(vNode)) {
if (vNode?.tag === SuspenseComponent && canCapturePromise(vNode)) {
if (vNode.suspensePromises === null) {
vNode.suspensePromises = new Set();
}
@ -196,36 +200,8 @@ export function handleSuspenseChildThrowError(parent: VNode, processing: VNode,
return false;
}
function canCapturePromise(vNode: VNode): boolean {
return vNode.suspenseChildStatus !== SuspenseChildStatus.ShowFallback && vNode.props.fallback !== undefined;
}
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
// 对于每个promise添加一个侦听器以便当它resolve时重新渲染
export function listenToPromise(suspenseVNode: VNode) {
const promises: Set<PromiseType<any>> | null = suspenseVNode.suspensePromises;
if (promises !== null) {
suspenseVNode.suspensePromises = null;
// 记录已经监听的 promise
let promiseCache = suspenseVNode.realNode;
if (promiseCache === null) {
// @ts-ignore
promiseCache = suspenseVNode.realNode = new PossiblyWeakSet();
}
promises.forEach(promise => {
const resole = resolvePromise.bind(null, suspenseVNode, promise);
if (!promiseCache.has(promise)) {
promiseCache.add(promise);
// 监听promise
promise.then(resole, resole);
}
});
}
}
function resolvePromise(suspenseVNode: VNode, promise: PromiseType<any>) {
const promiseCache = suspenseVNode.realNode;
if (promiseCache !== null) {
@ -238,4 +214,27 @@ function resolvePromise(suspenseVNode: VNode, promise: PromiseType<any>) {
}
}
// 对于每个promise添加一个侦听器以便当它resolve时重新渲染
export function listenToPromise(suspenseVNode: VNode) {
const promises: Set<PromiseType<any>> | null = suspenseVNode.suspensePromises;
if (promises !== null) {
suspenseVNode.suspensePromises = null;
// 记录已经监听的 promise
let promiseCache = suspenseVNode.realNode;
if (promiseCache === null) {
// @ts-ignore
promiseCache = new PossiblyWeakSet();
suspenseVNode.realNode = new PossiblyWeakSet();
}
promises.forEach(promise => {
const resole = resolvePromise.bind(null, suspenseVNode, promise);
if (!promiseCache.has(promise)) {
promiseCache.add(promise);
// 监听promise
promise.then(resole, resole);
}
});
}
}

View File

@ -6,10 +6,6 @@ import {resetNamespaceCtx, setNamespaceCtx} from '../ContextSaver';
import {resetOldCtx} from '../components/context/CompatibleContext';
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
export function captureRender(processing: VNode): VNode | null {
return updateTreeRoot(processing);
}
export function bubbleRender(processing: VNode) {
resetNamespaceCtx(processing);
resetOldCtx(processing);
@ -40,3 +36,7 @@ function updateTreeRoot(processing) {
processing.child = createVNodeChildren(processing, newElement);
return processing.child;
}
export function captureRender(processing: VNode): VNode | null {
return updateTreeRoot(processing);
}

View File

@ -25,9 +25,11 @@ export function callDerivedStateFromProps(
const newState = getDerivedStateFromProps(nextProps, oldState);
// 组件未返回state,需要返回旧的preState
processing.state = newState === null || newState === undefined
? oldState
: { ...oldState, ...newState };
if (newState) {
processing.state = { ...oldState, ...newState };
return;
}
processing.state = oldState;
}
}
@ -40,7 +42,7 @@ function changeStateContent(type: UpdateState, content: object, callback: Callba
if (type === UpdateState.Update || type === UpdateState.Override) {
update.content = content;
}
if (callback !== undefined && callback !== null) {
if (callback) {
update.callback = callback;
}