Match-id-8d414d34e1e31da012f05c0990166fc2746380a1
This commit is contained in:
commit
e79a882c8a
|
@ -84,3 +84,7 @@ const types = ['button', 'input', 'select', 'textarea'];
|
||||||
export function shouldAutoFocus(tagName: string, props: Props): boolean {
|
export function shouldAutoFocus(tagName: string, props: Props): boolean {
|
||||||
return types.includes(tagName) ? Boolean(props.autoFocus) : false;
|
return types.includes(tagName) ? Boolean(props.autoFocus) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNotNull(object: any): boolean {
|
||||||
|
return object !== null && object !== undefined;
|
||||||
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ export function isInvalidValue(
|
||||||
propDetails: PropDetails | null,
|
propDetails: PropDetails | null,
|
||||||
isNativeTag: boolean
|
isNativeTag: boolean
|
||||||
): boolean {
|
): boolean {
|
||||||
if (value == null) {
|
if (value === null || value === undefined) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ export function validateProps(type, props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// style属性必须是对象
|
// style属性必须是对象
|
||||||
if (props.style != null && typeof props.style !== 'object') {
|
if (props.style !== null && props.style !== undefined && typeof props.style !== 'object') {
|
||||||
throw new Error('style should be a object.');
|
throw new Error('style should be a object.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ function getInitValue(dom: HTMLInputElement, props: Props) {
|
||||||
export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
|
export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
|
||||||
// checked属于必填属性,无法置
|
// checked属于必填属性,无法置
|
||||||
let { checked } = props;
|
let { checked } = props;
|
||||||
if (checked == null) {
|
if (checked === undefined) {
|
||||||
checked = getInitValue(dom, props).initChecked;
|
checked = getInitValue(dom, props).initChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
|
||||||
export function updateInputValue(dom: HTMLInputElement, props: Props) {
|
export function updateInputValue(dom: HTMLInputElement, props: Props) {
|
||||||
const { value, checked } = props;
|
const { value, checked } = props;
|
||||||
|
|
||||||
if (value != null) {
|
if (value !== undefined) {
|
||||||
// 处理 dom.value 逻辑
|
// 处理 dom.value 逻辑
|
||||||
if (dom.value !== String(value)) {
|
if (dom.value !== String(value)) {
|
||||||
dom.value = String(value);
|
dom.value = String(value);
|
||||||
}
|
}
|
||||||
} else if (checked != null) {
|
} else if (checked !== undefined) {
|
||||||
updateCommonProp(dom, 'checked', checked, true);
|
updateCommonProp(dom, 'checked', checked, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ export function setInitInputValue(dom: HTMLInputElement, props: Props) {
|
||||||
const { value, defaultValue } = props;
|
const { value, defaultValue } = props;
|
||||||
const { initValue, initChecked } = getInitValue(dom, props);
|
const { initValue, initChecked } = getInitValue(dom, props);
|
||||||
|
|
||||||
if (value != null || defaultValue != null) {
|
if (value !== undefined || defaultValue !== undefined) {
|
||||||
// value 的使用优先级 value 属性 > defaultValue 属性 > 空字符串
|
// value 的使用优先级 value 属性 > defaultValue 属性 > 空字符串
|
||||||
const initValueStr = String(initValue);
|
const initValueStr = String(initValue);
|
||||||
|
|
||||||
|
|
|
@ -69,18 +69,18 @@ export function updateSelectValue(dom: HorizonSelect, props: Props, isInit = fal
|
||||||
dom._multiple = newMultiple;
|
dom._multiple = newMultiple;
|
||||||
|
|
||||||
// 设置了 value 属性
|
// 设置了 value 属性
|
||||||
if (value != null) {
|
if (value !== null && value !== undefined) {
|
||||||
updateValue(dom.options, value, newMultiple);
|
updateValue(dom.options, value, newMultiple);
|
||||||
} else if (oldMultiple !== newMultiple) {
|
} else if (oldMultiple !== newMultiple) {
|
||||||
// 修改了 multiple 属性
|
// 修改了 multiple 属性
|
||||||
// 切换 multiple 之后,如果设置了 defaultValue 需要重新应用
|
// 切换 multiple 之后,如果设置了 defaultValue 需要重新应用
|
||||||
if (defaultValue != null) {
|
if (defaultValue !== null && defaultValue !== undefined) {
|
||||||
updateValue(dom.options, defaultValue, newMultiple);
|
updateValue(dom.options, defaultValue, newMultiple);
|
||||||
} else {
|
} else {
|
||||||
// 恢复到未选定状态
|
// 恢复到未选定状态
|
||||||
updateValue(dom.options, newMultiple ? [] : '', newMultiple);
|
updateValue(dom.options, newMultiple ? [] : '', newMultiple);
|
||||||
}
|
}
|
||||||
} else if (isInit && defaultValue != null) {
|
} else if (isInit && defaultValue !== null && defaultValue !== undefined) {
|
||||||
// 设置了 defaultValue 属性
|
// 设置了 defaultValue 属性
|
||||||
updateValue(dom.options, defaultValue, newMultiple);
|
updateValue(dom.options, defaultValue, newMultiple);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { Props } from '../utils/Interface';
|
||||||
function getInitValue(props: Props) {
|
function getInitValue(props: Props) {
|
||||||
const { value } = props;
|
const { value } = props;
|
||||||
|
|
||||||
if (value == null) {
|
if (value === undefined) {
|
||||||
const { defaultValue, children } = props;
|
const { defaultValue, children } = props;
|
||||||
let initValue = defaultValue;
|
let initValue = defaultValue;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ function getInitValue(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultValue 属性未配置,置为空字符串
|
// defaultValue 属性未配置,置为空字符串
|
||||||
initValue = initValue != null ? initValue : '';
|
initValue = initValue ?? '';
|
||||||
return initValue;
|
return initValue;
|
||||||
} else {
|
} else {
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -62,13 +62,6 @@ function isCaptureEvent(horizonEventName) {
|
||||||
return horizonEventName.slice(-7) === 'Capture';
|
return horizonEventName.slice(-7) === 'Capture';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 利用冒泡事件模拟不冒泡事件,需要直接在根节点绑定
|
|
||||||
export function listenSimulatedDelegatedEvents(root: VNode) {
|
|
||||||
for (let i = 0; i < simulatedDelegatedEvents.length; i++) {
|
|
||||||
lazyDelegateOnRoot(root, simulatedDelegatedEvents[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 事件懒委托,当用户定义事件后,再进行委托到根节点
|
// 事件懒委托,当用户定义事件后,再进行委托到根节点
|
||||||
export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
|
export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
|
||||||
currentRoot.delegatedEvents.add(eventName);
|
currentRoot.delegatedEvents.add(eventName);
|
||||||
|
@ -80,11 +73,8 @@ export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
|
||||||
const nativeFullName = isCapture ? nativeEvent + 'capture' : nativeEvent;
|
const nativeFullName = isCapture ? nativeEvent + 'capture' : nativeEvent;
|
||||||
|
|
||||||
// 事件存储在DOM节点属性,避免多个VNode(root和portal)对应同一个DOM, 造成事件重复监听
|
// 事件存储在DOM节点属性,避免多个VNode(root和portal)对应同一个DOM, 造成事件重复监听
|
||||||
let events = currentRoot.realNode.$EV;
|
currentRoot.realNode.$EV = currentRoot.realNode.$EV ?? {};
|
||||||
|
const events = currentRoot.realNode.$EV;
|
||||||
if (!events) {
|
|
||||||
events = (currentRoot.realNode as any).$EV = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!events[nativeFullName]) {
|
if (!events[nativeFullName]) {
|
||||||
events[nativeFullName] = listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture);
|
events[nativeFullName] = listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture);
|
||||||
|
@ -92,6 +82,13 @@ export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 利用冒泡事件模拟不冒泡事件,需要直接在根节点绑定
|
||||||
|
export function listenSimulatedDelegatedEvents(root: VNode) {
|
||||||
|
for (let i = 0; i < simulatedDelegatedEvents.length; i++) {
|
||||||
|
lazyDelegateOnRoot(root, simulatedDelegatedEvents[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 通过horizon事件名获取到native事件名
|
// 通过horizon事件名获取到native事件名
|
||||||
function getNativeEvtName(horizonEventName, capture) {
|
function getNativeEvtName(horizonEventName, capture) {
|
||||||
let nativeName;
|
let nativeName;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getVNodeProps } from '../dom/DOMInternalKeys';
|
import { getVNodeProps } from '../dom/DOMInternalKeys';
|
||||||
import { getDomTag } from '../dom/utils/Common';
|
import { getDomTag, isNotNull } from '../dom/utils/Common';
|
||||||
import { Props } from '../dom/utils/Interface';
|
import { Props } from '../dom/utils/Interface';
|
||||||
import { updateTextareaValue } from '../dom/valueHandler/TextareaValueHandler';
|
import { updateTextareaValue } from '../dom/valueHandler/TextareaValueHandler';
|
||||||
import { updateInputHandlerIfChanged } from '../dom/valueHandler/ValueChangeHandler';
|
import { updateInputHandlerIfChanged } from '../dom/valueHandler/ValueChangeHandler';
|
||||||
|
@ -41,14 +41,14 @@ function controlInputValue(inputDom: HTMLInputElement, props: Props) {
|
||||||
const { name, type } = props;
|
const { name, type } = props;
|
||||||
|
|
||||||
// 如果是 radio,找出同一form内,name相同的Radio,更新它们Handler的Value
|
// 如果是 radio,找出同一form内,name相同的Radio,更新它们Handler的Value
|
||||||
if (type === 'radio' && name != null) {
|
if (type === 'radio' && isNotNull(name)) {
|
||||||
const radioList = document.querySelectorAll<HTMLInputElement>(`input[type="radio"][name="${name}"]`);
|
const radioList = document.querySelectorAll<HTMLInputElement>(`input[type="radio"][name="${name}"]`);
|
||||||
for (let i = 0; i < radioList.length; i++) {
|
for (let i = 0; i < radioList.length; i++) {
|
||||||
const radio = radioList[i];
|
const radio = radioList[i];
|
||||||
if (radio === inputDom) {
|
if (radio === inputDom) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (radio.form != null && inputDom.form != null && radio.form !== inputDom.form) {
|
if (isNotNull(radio.form) && isNotNull(inputDom.form) && radio.form !== inputDom.form) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,34 +87,30 @@ export function getListenersFromTree(
|
||||||
return listeners;
|
return listeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取enter和leave事件队列
|
|
||||||
export function collectMouseListeners(
|
// 获取父节点
|
||||||
leaveEvent: null | WrappedEvent,
|
function getParent(inst: VNode | null): VNode | null {
|
||||||
enterEvent: null | WrappedEvent,
|
if (inst === null) {
|
||||||
from: VNode | null,
|
return null;
|
||||||
to: VNode | null,
|
|
||||||
): ListenerUnitList {
|
|
||||||
// 确定公共父节点,作为在树上遍历的终点
|
|
||||||
const commonParent = from && to ? getCommonAncestor(from, to) : null;
|
|
||||||
let leaveEventList: ListenerUnitList = [];
|
|
||||||
if (from && leaveEvent) {
|
|
||||||
// 遍历树,获取绑定的leave事件
|
|
||||||
leaveEventList = getMouseListenersFromTree(
|
|
||||||
leaveEvent,
|
|
||||||
from,
|
|
||||||
commonParent,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let enterEventList: ListenerUnitList = [];
|
do {
|
||||||
if (to && enterEvent) {
|
inst = inst.parent;
|
||||||
// 先触发父节点enter事件,所以需要逆序
|
} while (inst && inst.tag !== DomComponent);
|
||||||
enterEventList = getMouseListenersFromTree(
|
return inst || null;
|
||||||
enterEvent,
|
}
|
||||||
to,
|
|
||||||
commonParent,
|
// 寻找两个节点的共同最近祖先,如果没有则返回null
|
||||||
).reverse();
|
function getCommonAncestor(instA: VNode, instB: VNode): VNode | null {
|
||||||
|
const parentsSet = new Set<VNode>();
|
||||||
|
for (let tempA: VNode | null = instA; tempA; tempA = getParent(tempA)) {
|
||||||
|
parentsSet.add(tempA);
|
||||||
}
|
}
|
||||||
return [...leaveEventList, ...enterEventList];
|
for (let tempB: VNode | null = instB; tempB; tempB = getParent(tempB)) {
|
||||||
|
if (parentsSet.has(tempB)) {
|
||||||
|
return tempB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMouseListenersFromTree(
|
function getMouseListenersFromTree(
|
||||||
|
@ -149,27 +145,32 @@ function getMouseListenersFromTree(
|
||||||
return listeners;
|
return listeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 寻找两个节点的共同最近祖先,如果没有则返回null
|
// 获取enter和leave事件队列
|
||||||
function getCommonAncestor(instA: VNode, instB: VNode): VNode | null {
|
export function collectMouseListeners(
|
||||||
const parentsSet = new Set<VNode>();
|
leaveEvent: null | WrappedEvent,
|
||||||
for (let tempA: VNode | null = instA; tempA; tempA = getParent(tempA)) {
|
enterEvent: null | WrappedEvent,
|
||||||
parentsSet.add(tempA);
|
from: VNode | null,
|
||||||
|
to: VNode | null,
|
||||||
|
): ListenerUnitList {
|
||||||
|
// 确定公共父节点,作为在树上遍历的终点
|
||||||
|
const commonParent = from && to ? getCommonAncestor(from, to) : null;
|
||||||
|
let leaveEventList: ListenerUnitList = [];
|
||||||
|
if (from && leaveEvent) {
|
||||||
|
// 遍历树,获取绑定的leave事件
|
||||||
|
leaveEventList = getMouseListenersFromTree(
|
||||||
|
leaveEvent,
|
||||||
|
from,
|
||||||
|
commonParent,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (let tempB: VNode | null = instB; tempB; tempB = getParent(tempB)) {
|
let enterEventList: ListenerUnitList = [];
|
||||||
if (parentsSet.has(tempB)) {
|
if (to && enterEvent) {
|
||||||
return tempB;
|
// 先触发父节点enter事件,所以需要逆序
|
||||||
|
enterEventList = getMouseListenersFromTree(
|
||||||
|
enterEvent,
|
||||||
|
to,
|
||||||
|
commonParent,
|
||||||
|
).reverse();
|
||||||
}
|
}
|
||||||
}
|
return [...leaveEventList, ...enterEventList];
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取父节点
|
|
||||||
function getParent(inst: VNode | null): VNode | null {
|
|
||||||
if (inst === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
inst = inst.parent;
|
|
||||||
} while (inst && inst.tag !== DomComponent);
|
|
||||||
return inst || null;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ function bubbleVNode(vNode: VNode): void {
|
||||||
node = parent;
|
node = parent;
|
||||||
// 更新processing,抛出异常时可以使用
|
// 更新processing,抛出异常时可以使用
|
||||||
processing = node;
|
processing = node;
|
||||||
} while (node !== null);
|
} while (node);
|
||||||
|
|
||||||
// 修改结果
|
// 修改结果
|
||||||
if (getBuildResult() === BuildInComplete) {
|
if (getBuildResult() === BuildInComplete) {
|
||||||
|
@ -180,7 +180,7 @@ function getChildByIndex(vNode: VNode, idx: number) {
|
||||||
let node = vNode.child;
|
let node = vNode.child;
|
||||||
for (let i = 0; i < idx; i++) {
|
for (let i = 0; i < idx; i++) {
|
||||||
// 场景:当组件被销毁,业务若异步(定时器)调用setState修改状态,可能出现路径错误,此处进行保护。
|
// 场景:当组件被销毁,业务若异步(定时器)调用setState修改状态,可能出现路径错误,此处进行保护。
|
||||||
if (node == null) {
|
if (node === null || node === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ export function calcStartUpdateVNode(treeRoot: VNode) {
|
||||||
const pathIndex = Number(startNodePath[i]);
|
const pathIndex = Number(startNodePath[i]);
|
||||||
node = getChildByIndex(node, pathIndex)!;
|
node = getChildByIndex(node, pathIndex)!;
|
||||||
// 路径错误时,回退到从根更新
|
// 路径错误时,回退到从根更新
|
||||||
if (node == null) {
|
if (node === null) {
|
||||||
return treeRoot;
|
return treeRoot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,6 +182,10 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +378,7 @@ function diffArrayNodesHandler(parentNode: VNode, firstChild: VNode | null, newC
|
||||||
// 4. 新节点还有一部分,但是老节点已经没有了
|
// 4. 新节点还有一部分,但是老节点已经没有了
|
||||||
if (oldNode === null) {
|
if (oldNode === null) {
|
||||||
let isDirectAdd = false;
|
let isDirectAdd = false;
|
||||||
// TODO: 是否可以扩大至非dom类型节点
|
// 是否可以扩大至非dom类型节点待确认
|
||||||
// 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点
|
// 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点
|
||||||
if (
|
if (
|
||||||
parentNode.tag === DomComponent &&
|
parentNode.tag === DomComponent &&
|
||||||
|
@ -513,7 +517,7 @@ function diffIteratorNodesHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新节点是字符串类型
|
// 新节点是字符串类型
|
||||||
function diffStringNodeHandler(parentNode: VNode, newChild: any, firstChildVNode: VNode, isComparing: boolean) {
|
function diffStringNodeHandler(parentNode: VNode, newChild: any, firstChildVNode: VNode | null, isComparing: boolean) {
|
||||||
let newTextNode: VNode | null = null;
|
let newTextNode: VNode | null = null;
|
||||||
|
|
||||||
// 第一个vNode是Text,则复用
|
// 第一个vNode是Text,则复用
|
||||||
|
@ -560,7 +564,7 @@ function diffObjectNodeHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultNode: VNode | null = null;
|
let resultNode: VNode | null = null;
|
||||||
let startDelVNode = firstChildVNode;
|
let startDelVNode: VNode | null = firstChildVNode;
|
||||||
if (newChild.vtype === TYPE_COMMON_ELEMENT) {
|
if (newChild.vtype === TYPE_COMMON_ELEMENT) {
|
||||||
if (canReuseNode) {
|
if (canReuseNode) {
|
||||||
// 可以复用
|
// 可以复用
|
||||||
|
|
|
@ -52,7 +52,7 @@ export function createHook(state: any = null): Hook<any, any> {
|
||||||
return currentHook;
|
return currentHook;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>) {
|
export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>): Hook<any, any> | null {
|
||||||
return hooks[hook.hIndex + 1] || null;
|
return hooks[hook.hIndex + 1] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,9 @@ import { useLayoutEffectImpl } from './UseEffectHook';
|
||||||
import { getHookStage } from './HookStage';
|
import { getHookStage } from './HookStage';
|
||||||
import { throwNotInFuncError } from './BaseHook';
|
import { throwNotInFuncError } from './BaseHook';
|
||||||
import type { Ref } from './HookType';
|
import type { Ref } from './HookType';
|
||||||
|
import { isNotNull } from '../../dom/utils/Common';
|
||||||
|
|
||||||
function isNotNull(object: any): boolean {
|
function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (() => void) | null {
|
||||||
return object !== null && object !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (() => void) | void {
|
|
||||||
if (typeof ref === 'function') {
|
if (typeof ref === 'function') {
|
||||||
const value = func();
|
const value = func();
|
||||||
ref(value);
|
ref(value);
|
||||||
|
@ -37,6 +34,7 @@ function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (()
|
||||||
ref.current = null;
|
ref.current = null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useImperativeHandleImpl<R>(
|
export function useImperativeHandleImpl<R>(
|
||||||
|
|
|
@ -64,7 +64,7 @@ function handleContextChange(processing: VNode, context: ContextType<any>): void
|
||||||
node => {
|
node => {
|
||||||
const depContexts = node.depContexts;
|
const depContexts = node.depContexts;
|
||||||
if (depContexts && depContexts.length) {
|
if (depContexts && depContexts.length) {
|
||||||
isMatch = matchDependencies(depContexts, context, node) ?? isMatch;
|
isMatch = matchDependencies(depContexts, context, node) || isMatch;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
node =>
|
node =>
|
||||||
|
|
|
@ -54,7 +54,7 @@ export function bubbleRender(processing: VNode) {
|
||||||
|
|
||||||
const type = processing.type;
|
const type = processing.type;
|
||||||
const newProps = processing.props;
|
const newProps = processing.props;
|
||||||
if (!processing.isCreated && processing.realNode != null) {
|
if (!processing.isCreated && processing.realNode !== null) {
|
||||||
// 更新dom属性
|
// 更新dom属性
|
||||||
updateDom(processing, type, newProps);
|
updateDom(processing, type, newProps);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import type { VNode } from '../Types';
|
||||||
import { throwIfTrue } from '../utils/throwIfTrue';
|
import { throwIfTrue } from '../utils/throwIfTrue';
|
||||||
import { newTextDom } from '../../dom/DOMOperator';
|
import { newTextDom } from '../../dom/DOMOperator';
|
||||||
import { FlagUtils } from '../vnode/VNodeFlags';
|
import { FlagUtils } from '../vnode/VNodeFlags';
|
||||||
|
import { isNull } from '../../dom/utils/Common';
|
||||||
|
|
||||||
export function captureRender(): VNode | null {
|
export function captureRender(): VNode | null {
|
||||||
return null;
|
return null;
|
||||||
|
@ -26,7 +27,7 @@ export function captureRender(): VNode | null {
|
||||||
export function bubbleRender(processing: VNode) {
|
export function bubbleRender(processing: VNode) {
|
||||||
const newText = processing.props;
|
const newText = processing.props;
|
||||||
|
|
||||||
if (!processing.isCreated && processing.realNode != null) {
|
if (!processing.isCreated && processing.realNode !== null) {
|
||||||
// 更新
|
// 更新
|
||||||
const oldText = processing.oldProps;
|
const oldText = processing.oldProps;
|
||||||
// 如果文本不同,将其标记为更新
|
// 如果文本不同,将其标记为更新
|
||||||
|
|
|
@ -165,7 +165,7 @@ function canCapturePromise(vNode: VNode | null): boolean {
|
||||||
|
|
||||||
// 处理Suspense子组件抛出的promise
|
// 处理Suspense子组件抛出的promise
|
||||||
export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, promise: PromiseType<any>): boolean {
|
export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, promise: PromiseType<any>): boolean {
|
||||||
let vNode = parent;
|
let vNode: VNode | null = parent;
|
||||||
|
|
||||||
// 向上找到最近的不在fallback状态的Suspense,并触发重新渲染
|
// 向上找到最近的不在fallback状态的Suspense,并触发重新渲染
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function callDerivedStateFromProps(
|
||||||
const newState = getDerivedStateFromProps(nextProps, oldState);
|
const newState = getDerivedStateFromProps(nextProps, oldState);
|
||||||
|
|
||||||
// 组件未返回state,需要返回旧的preState
|
// 组件未返回state,需要返回旧的preState
|
||||||
processing.state = newState === null || newState === undefined ? oldState : { ...oldState, ...newState };
|
processing.state = newState ? { ...oldState, ...newState } : oldState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ function callRenderQueue() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let callback;
|
let callback;
|
||||||
while ((callback = renderQueue.shift())) {
|
while (callback = renderQueue.shift()) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,12 +63,12 @@ export function add(node: Node): void {
|
||||||
|
|
||||||
export function first(): Node | null {
|
export function first(): Node | null {
|
||||||
const val: Node | null | undefined = taskQueue[0];
|
const val: Node | null | undefined = taskQueue[0];
|
||||||
return val !== undefined ? val : null;
|
return val ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shift(): Node | null {
|
export function shift(): Node | null {
|
||||||
const val = taskQueue.shift();
|
const val = taskQueue.shift();
|
||||||
return val !== undefined ? val : null;
|
return val ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function remove(node: Node) {
|
export function remove(node: Node) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ export function createUndeterminedVNode(type, key, props, source: Source | null)
|
||||||
vNodeTag = typeMap[type.vtype];
|
vNodeTag = typeMap[type.vtype];
|
||||||
isLazy = type.vtype === TYPE_LAZY;
|
isLazy = type.vtype === TYPE_LAZY;
|
||||||
} else {
|
} else {
|
||||||
throw Error(`Component type is invalid, got: ${type == null ? type : componentType}`);
|
throw Error(`Component type is invalid, got: ${type === null || type === undefined ? type : componentType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vNode = newVirtualNode(vNodeTag, key, props);
|
const vNode = newVirtualNode(vNodeTag, key, props);
|
||||||
|
@ -183,7 +183,7 @@ export function createTreeRootVNode(container) {
|
||||||
return vNode;
|
return vNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 暂时保留给测试用例使用,后续修改测试用例
|
// 暂时保留给测试用例使用,后续修改测试用例
|
||||||
export function createVNode(tag: VNodeTag | string, ...secondArg) {
|
export function createVNode(tag: VNodeTag | string, ...secondArg) {
|
||||||
let vNode = null;
|
let vNode = null;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
|
|
|
@ -36,71 +36,71 @@ export const ForceUpdate = /** */ 1 << 12; // For suspense
|
||||||
export const Clear = /** */ 1 << 13;
|
export const Clear = /** */ 1 << 13;
|
||||||
const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
|
const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
|
||||||
|
|
||||||
export class FlagUtils {
|
export const FlagUtils = {
|
||||||
static removeFlag(node: VNode, flag: number) {
|
removeFlag(node: VNode, flag: number) {
|
||||||
node.flags &= ~flag;
|
node.flags &= ~flag;
|
||||||
}
|
},
|
||||||
|
|
||||||
static removeLifecycleEffectFlags(node) {
|
removeLifecycleEffectFlags(node) {
|
||||||
node.flags &= ~LifecycleEffectArr;
|
node.flags &= ~LifecycleEffectArr;
|
||||||
}
|
},
|
||||||
|
|
||||||
static hasAnyFlag(node: VNode) {
|
hasAnyFlag(node: VNode) {
|
||||||
// 有标志位
|
// 有标志位
|
||||||
return node.flags !== InitFlag;
|
return node.flags !== InitFlag;
|
||||||
}
|
},
|
||||||
|
|
||||||
static hasFlag(node: VNode, flag) {
|
hasFlag(node: VNode, flag) {
|
||||||
return (node.flags & flag) !== 0;
|
return (node.flags & flag) !== 0;
|
||||||
}
|
},
|
||||||
|
|
||||||
static setNoFlags(node: VNode) {
|
setNoFlags(node: VNode) {
|
||||||
node.flags = InitFlag;
|
node.flags = InitFlag;
|
||||||
}
|
},
|
||||||
|
|
||||||
static markAddition(node: VNode) {
|
markAddition(node: VNode) {
|
||||||
node.flags |= Addition;
|
node.flags |= Addition;
|
||||||
}
|
},
|
||||||
|
|
||||||
static setAddition(node: VNode) {
|
setAddition(node: VNode) {
|
||||||
node.flags = Addition;
|
node.flags = Addition;
|
||||||
}
|
},
|
||||||
|
|
||||||
static markDirectAddition(node: VNode) {
|
markDirectAddition(node: VNode) {
|
||||||
node.flags |= DirectAddition;
|
node.flags |= DirectAddition;
|
||||||
}
|
},
|
||||||
static markUpdate(node: VNode) {
|
markUpdate(node: VNode) {
|
||||||
node.flags |= Update;
|
node.flags |= Update;
|
||||||
}
|
},
|
||||||
static setDeletion(node: VNode) {
|
setDeletion(node: VNode) {
|
||||||
node.flags = Deletion;
|
node.flags = Deletion;
|
||||||
}
|
},
|
||||||
static markContentReset(node: VNode) {
|
markContentReset(node: VNode) {
|
||||||
node.flags |= ResetText;
|
node.flags |= ResetText;
|
||||||
}
|
},
|
||||||
static markCallback(node: VNode) {
|
markCallback(node: VNode) {
|
||||||
node.flags |= Callback;
|
node.flags |= Callback;
|
||||||
}
|
},
|
||||||
static markDidCapture(node: VNode) {
|
markDidCapture(node: VNode) {
|
||||||
node.flags |= DidCapture;
|
node.flags |= DidCapture;
|
||||||
}
|
},
|
||||||
static markShouldCapture(node: VNode) {
|
markShouldCapture(node: VNode) {
|
||||||
node.flags |= ShouldCapture;
|
node.flags |= ShouldCapture;
|
||||||
}
|
},
|
||||||
static markRef(node: VNode) {
|
markRef(node: VNode) {
|
||||||
node.flags |= Ref;
|
node.flags |= Ref;
|
||||||
}
|
},
|
||||||
static markSnapshot(node: VNode) {
|
markSnapshot(node: VNode) {
|
||||||
node.flags |= Snapshot;
|
node.flags |= Snapshot;
|
||||||
}
|
},
|
||||||
static markInterrupted(node: VNode) {
|
markInterrupted(node: VNode) {
|
||||||
node.flags |= Interrupted;
|
node.flags |= Interrupted;
|
||||||
}
|
},
|
||||||
static markForceUpdate(node: VNode) {
|
markForceUpdate(node: VNode) {
|
||||||
node.flags |= ForceUpdate;
|
node.flags |= ForceUpdate;
|
||||||
}
|
},
|
||||||
|
|
||||||
static markClear(node: VNode) {
|
markClear(node: VNode) {
|
||||||
node.flags |= Clear;
|
node.flags |= Clear;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue