Match-id-cc46c9f90ee2c1f0d758534ce54c0583577b42ce

This commit is contained in:
* 2022-10-25 20:30:14 +08:00 committed by *
commit b0f4ffa7bf
84 changed files with 622 additions and 846 deletions

View File

@ -120,7 +120,7 @@ const Horizon = {
isMemo,
isPortal,
isContextProvider,
isContextConsumer
isContextConsumer,
};
export const version = __VERSION__;
@ -171,7 +171,7 @@ export {
isMemo,
isPortal,
isContextProvider,
isContextConsumer
isContextConsumer,
};
export default Horizon;

View File

@ -18,16 +18,9 @@
*/
import type { VNode } from '../renderer/Types';
import type {
Container,
Props,
} from './DOMOperator';
import type { Container, Props } from './DOMOperator';
import {
DomComponent,
DomText,
TreeRoot,
} from '../renderer/vnode/VNodeTags';
import { DomComponent, DomText, TreeRoot } from '../renderer/vnode/VNodeTags';
const INTERNAL_VNODE = '_horizon_VNode';
const INTERNAL_PROPS = '_horizon_Props';
@ -43,10 +36,7 @@ export function getDom(vNode: VNode): Element | Text | null {
}
// 将 VNode 属性相关信息挂到 DOM 对象的特定属性上
export function saveVNode(
vNode: VNode,
dom: Element | Text | Container,
): void {
export function saveVNode(vNode: VNode, dom: Element | Text | Container): void {
dom[INTERNAL_VNODE] = vNode;
}

View File

@ -13,27 +13,15 @@
* See the Mulan PSL v2 for more details.
*/
import {
saveVNode,
updateVNodeProps,
} from './DOMInternalKeys';
import {
createDom,
} from './utils/DomCreator';
import { saveVNode, updateVNodeProps } from './DOMInternalKeys';
import { createDom } from './utils/DomCreator';
import { getSelectionInfo, resetSelectionRange, SelectionData } from './SelectionRangeHandler';
import { shouldAutoFocus } from './utils/Common';
import { NSS } from './utils/DomCreator';
import { adjustStyleValue } from './DOMPropertiesHandler/StyleHandler';
import type { VNode } from '../renderer/Types';
import {
setInitValue,
getPropsWithoutValue,
updateValue,
} from './valueHandler';
import {
compareProps,
setDomProps,
} from './DOMPropertiesHandler/DOMPropertiesHandler';
import { setInitValue, getPropsWithoutValue, updateValue } from './valueHandler';
import { compareProps, setDomProps } from './DOMPropertiesHandler/DOMPropertiesHandler';
import { isNativeElement, validateProps } from './validators/ValidateProps';
import { watchValueChange } from './valueHandler/ValueChangeHandler';
import { DomComponent, DomText } from '../renderer/vnode/VNodeTags';
@ -81,12 +69,7 @@ export function resetAfterSubmit(): void {
}
// 创建 DOM 对象
export function newDom(
tagName: string,
props: Props,
parentNamespace: string,
vNode: VNode,
): Element {
export function newDom(tagName: string, props: Props, parentNamespace: string, vNode: VNode): Element {
const dom: Element = createDom(tagName, parentNamespace);
// 将 vNode 节点挂到 DOM 对象上
saveVNode(vNode, dom);
@ -119,12 +102,7 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo
}
// 准备更新之前进行一系列校验 DOM寻找属性差异等准备工作
export function getPropChangeList(
dom: Element,
type: string,
lastRawProps: Props,
nextRawProps: Props,
): Object {
export function getPropChangeList(dom: Element, type: string, lastRawProps: Props, nextRawProps: Props): Object {
// 校验两个对象的不同
validateProps(type, nextRawProps);
@ -151,10 +129,7 @@ export function isTextChild(type: string, props: Props): boolean {
}
}
export function newTextDom(
text: string,
processing: VNode,
): Text {
export function newTextDom(text: string, processing: VNode): Text {
const textNode: Text = document.createTextNode(text);
saveVNode(processing, textNode);
return textNode;
@ -198,26 +173,16 @@ export function clearText(dom: Element): void {
}
// 添加child元素
export function appendChildElement(
parent: Element | Container,
child: Element | Text
): void {
export function appendChildElement(parent: Element | Container, child: Element | Text): void {
parent.appendChild(child);
}
// 插入dom元素
export function insertDomBefore(
parent: Element | Container,
child: Element | Text,
beforeChild: Element | Text,
) {
export function insertDomBefore(parent: Element | Container, child: Element | Text, beforeChild: Element | Text) {
parent.insertBefore(child, beforeChild);
}
export function removeChildDom(
parent: Element | Container,
child: Element | Text
) {
export function removeChildDom(parent: Element | Container, child: Element | Text) {
parent.removeChild(child);
}

View File

@ -81,11 +81,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object {
styleProp = styleProps[j];
updatesForStyle[styleProp] = '';
}
} else if (
propName === 'autoFocus' ||
propName === 'children' ||
propName === 'dangerouslySetInnerHTML'
) {
} else if (propName === 'autoFocus' || propName === 'children' || propName === 'dangerouslySetInnerHTML') {
continue;
} else if (isEventProp(propName)) {
if (!allDelegatedHorizonEvents.has(propName)) {

View File

@ -14,14 +14,16 @@
*/
function isNeedUnitCSS(styleName: string) {
return !(noUnitCSS.includes(styleName)
|| styleName.startsWith('borderImage')
|| styleName.startsWith('flex')
|| styleName.startsWith('gridRow')
|| styleName.startsWith('gridColumn')
|| styleName.startsWith('stroke')
|| styleName.startsWith('box')
|| styleName.endsWith('Opacity'));
return !(
noUnitCSS.includes(styleName) ||
styleName.startsWith('borderImage') ||
styleName.startsWith('flex') ||
styleName.startsWith('gridRow') ||
styleName.startsWith('gridColumn') ||
styleName.startsWith('stroke') ||
styleName.startsWith('box') ||
styleName.endsWith('Opacity')
);
}
/**
@ -50,7 +52,7 @@ export function setStyles(dom, styles) {
}
const style = dom.style;
Object.keys(styles).forEach((name) => {
Object.keys(styles).forEach(name => {
const styleVal = styles[name];
style[name] = adjustStyleValue(name, styleVal);
@ -60,5 +62,19 @@ export function setStyles(dom, styles) {
/**
* css
*/
const noUnitCSS = ['animationIterationCount', 'columnCount', 'columns', 'gridArea', 'fontWeight', 'lineClamp',
'lineHeight', 'opacity', 'order', 'orphans', 'tabSize', 'widows', 'zIndex', 'zoom'];
const noUnitCSS = [
'animationIterationCount',
'columnCount',
'columns',
'gridArea',
'fontWeight',
'lineClamp',
'lineHeight',
'opacity',
'order',
'orphans',
'tabSize',
'widows',
'zIndex',
'zoom',
];

View File

@ -13,25 +13,77 @@
* See the Mulan PSL v2 for more details.
*/
import {
getPropDetails,
PROPERTY_TYPE,
} from '../validators/PropertiesData';
import { getPropDetails, PROPERTY_TYPE } from '../validators/PropertiesData';
import { isInvalidValue } from '../validators/ValidateProps';
import { getNamespaceCtx } from '../../renderer/ContextSaver';
import { NSS } from '../utils/DomCreator';
import { getDomTag } from '../utils/Common';
const svgHumpAttr = new Set(['allowReorder', 'autoReverse', 'baseFrequency', 'baseProfile', 'calcMode', 'clipPathUnits',
'contentScriptType', 'contentStyleType', 'diffuseConstant', 'edgeMode', 'externalResourcesRequired', 'filterRes',
'filterUnits', 'glyphRef', 'gradientTransform', 'gradientUnits', 'kernelMatrix', 'kernelUnitLength', 'keyPoints',
'keySplines', 'keyTimes', 'lengthAdjust', 'limitingConeAngle', 'markerHeight', 'markerUnits', 'markerWidth',
'maskContentUnits', 'maskUnits', 'numOctaves', 'pathLength', 'patternContentUnits', 'patternTransform,',
'patternUnits', 'pointsAtX', 'pointsAtY', 'pointsAtZ', 'preserveAlpha', 'preserveAspectRatio', 'primitiveUnits',
'referrerPolicy', 'refX', 'refY', 'repeatCount', 'repeatDur', 'requiredExtensions', 'requiredFeatures',
'specularConstant', 'specularExponent', 'spreadMethod', 'startOffset', 'stdDeviation',
'stitchTiles', 'surfaceScale','systemLanguage', 'tableValues', 'targetX', 'targetY',
'textLength','viewBox', 'viewTarget', 'xChannelSelector','yChannelSelector', 'zoomAndPan']);
const svgHumpAttr = new Set([
'allowReorder',
'autoReverse',
'baseFrequency',
'baseProfile',
'calcMode',
'clipPathUnits',
'contentScriptType',
'contentStyleType',
'diffuseConstant',
'edgeMode',
'externalResourcesRequired',
'filterRes',
'filterUnits',
'glyphRef',
'gradientTransform',
'gradientUnits',
'kernelMatrix',
'kernelUnitLength',
'keyPoints',
'keySplines',
'keyTimes',
'lengthAdjust',
'limitingConeAngle',
'markerHeight',
'markerUnits',
'markerWidth',
'maskContentUnits',
'maskUnits',
'numOctaves',
'pathLength',
'patternContentUnits',
'patternTransform,',
'patternUnits',
'pointsAtX',
'pointsAtY',
'pointsAtZ',
'preserveAlpha',
'preserveAspectRatio',
'primitiveUnits',
'referrerPolicy',
'refX',
'refY',
'repeatCount',
'repeatDur',
'requiredExtensions',
'requiredFeatures',
'specularConstant',
'specularExponent',
'spreadMethod',
'startOffset',
'stdDeviation',
'stitchTiles',
'surfaceScale',
'systemLanguage',
'tableValues',
'targetX',
'targetY',
'textLength',
'viewBox',
'viewTarget',
'xChannelSelector',
'yChannelSelector',
'zoomAndPan',
]);
// 驼峰 变 “-”
function convertToLowerCase(str) {
@ -65,19 +117,22 @@ export function updateCommonProp(dom: Element, attrName: string, value: any, isN
dom.setAttribute(attrName, String(value));
}
} else if (['checked', 'multiple', 'muted', 'selected'].includes(propDetails.attrName)) {
if (value === null) { // 必填属性设置默认值
if (value === null) {
// 必填属性设置默认值
dom[propDetails.attrName] = false;
} else {
dom[propDetails.attrName] = value;
}
} else { // 处理其他普通属性
} else {
// 处理其他普通属性
if (value === null) {
dom.removeAttribute(propDetails.attrName);
} else {
const { type, attrNS } = propDetails; // 数据类型、固有属性命名空间
const attributeName = propDetails.attrName; // 固有属性名
let attributeValue;
if (type === PROPERTY_TYPE.BOOLEAN) { // 即可以用作标志又可以是属性值的属性
if (type === PROPERTY_TYPE.BOOLEAN) {
// 即可以用作标志又可以是属性值的属性
attributeValue = '';
} else {
attributeValue = String(value);

View File

@ -76,7 +76,8 @@ function isNodeContainsByTargetNode(targetNode, node) {
if (typeof targetNode.contains === 'function') {
return targetNode.contains(node); // 该的节点是否为目标节点的后代节点
}
if (typeof targetNode.compareDocumentPosition === 'function') { // compareDocumentPosition 数值,表示两个节点彼此做比较的位置
if (typeof targetNode.compareDocumentPosition === 'function') {
// compareDocumentPosition 数值,表示两个节点彼此做比较的位置
const CONTAINS_CODE = 16;
// 返回 16 代表 第二节点在第一节点内部
return targetNode.compareDocumentPosition(node) === CONTAINS_CODE;
@ -153,7 +154,8 @@ export function resetSelectionRange(preSelectionRangeData: SelectionData) {
let ancestor = preFocusedDom.parentNode;
// 查找先前的 focus 节点的先祖
while (ancestor) {
if (isElement(ancestor)) { // 是元素节点,就把先祖信息放到先祖数组中
if (isElement(ancestor)) {
// 是元素节点,就把先祖信息放到先祖数组中
// @ts-ignore
const { scrollLeft, scrollTop } = ancestor;
ancestors.push({

View File

@ -35,12 +35,15 @@ export function getIFrameFocusedDom() {
while (focusedDom instanceof currentWindow.HTMLIFrameElement) {
try {
// 访问 HTMLIframeElement 的 contentDocument 可能会导致浏览器抛出错误
if (typeof focusedDom.contentWindow.location.href === 'string') { // iframe 的内容为同源
if (typeof focusedDom.contentWindow.location.href === 'string') {
// iframe 的内容为同源
focusedDom = getFocusedDom(focusedDom.contentWindow.document);
} else { // 非同源 iframe 因为安全性原因无法获取其中的具体元素
} else {
// 非同源 iframe 因为安全性原因无法获取其中的具体元素
break;
}
} catch (e) { // 非同源 iframe 因为安全性原因无法获取其中的具体元素
} catch (e) {
// 非同源 iframe 因为安全性原因无法获取其中的具体元素
break;
}
}

View File

@ -1,4 +1,3 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
@ -21,10 +20,7 @@ export const NSS = {
};
// 创建DOM元素
export function createDom(
tagName: string,
parentNamespace: string,
): Element {
export function createDom(tagName: string, parentNamespace: string): Element {
let dom: Element;
const selfNamespace = NSS[tagName] || NSS.html;
const ns = parentNamespace !== NSS.html ? parentNamespace : selfNamespace;

View File

@ -13,23 +13,16 @@
* See the Mulan PSL v2 for more details.
*/
import {
getPropDetails, PROPERTY_TYPE, PropDetails,
} from './PropertiesData';
import { getPropDetails, PROPERTY_TYPE, PropDetails } from './PropertiesData';
const INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
// 是内置元素
export function isNativeElement(tagName: string, props: Record<string, any>) {
return !tagName.includes('-') && props.is === undefined;
}
function isInvalidBoolean(
attributeName: string,
value: any,
propDetails: PropDetails,
): boolean {
function isInvalidBoolean(attributeName: string, value: any, propDetails: PropDetails): boolean {
if (propDetails.type === PROPERTY_TYPE.SPECIAL) {
return false;
}
@ -78,7 +71,7 @@ export function isInvalidValue(
name: string,
value: any,
propDetails: PropDetails | null,
isNativeTag: boolean,
isNativeTag: boolean
): boolean {
if (value == null) {
return true;
@ -122,11 +115,7 @@ export function validateProps(type, props) {
const propString = invalidProps.map(prop => '`' + prop + '`').join(', ');
if (invalidProps.length >= 1) {
console.error(
'Invalid value for prop %s on <%s> tag.',
propString,
type,
);
console.error('Invalid value for prop %s on <%s> tag.', propString, type);
}
}
}

View File

@ -45,7 +45,8 @@ export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
export function updateInputValue(dom: HTMLInputElement, props: Props) {
const { value, checked } = props;
if (value != null) { // 处理 dom.value 逻辑
if (value != null) {
// 处理 dom.value 逻辑
if (dom.value !== String(value)) {
dom.value = String(value);
}

View File

@ -18,7 +18,7 @@ import {HorizonSelect, Props} from '../utils/Interface';
function updateMultipleValue(options, newValues) {
const newValueSet = new Set();
newValues.forEach((val) => {
newValues.forEach(val => {
newValueSet.add(String(val));
});
@ -61,7 +61,7 @@ export function getSelectPropsWithoutValue(dom: HorizonSelect, properties: Objec
};
}
export function updateSelectValue(dom: HorizonSelect, props: Props, isInit: boolean = false) {
export function updateSelectValue(dom: HorizonSelect, props: Props, isInit = false) {
const { value, defaultValue, multiple } = props;
const oldMultiple = dom._multiple !== undefined ? dom._multiple : dom.multiple;
@ -71,7 +71,8 @@ export function updateSelectValue(dom: HorizonSelect, props: Props, isInit: bool
// 设置了 value 属性
if (value != null) {
updateValue(dom.options, value, newMultiple);
} else if (oldMultiple !== newMultiple) { // 修改了 multiple 属性
} else if (oldMultiple !== newMultiple) {
// 修改了 multiple 属性
// 切换 multiple 之后,如果设置了 defaultValue 需要重新应用
if (defaultValue != null) {
updateValue(dom.options, defaultValue, newMultiple);
@ -79,7 +80,8 @@ export function updateSelectValue(dom: HorizonSelect, props: Props, isInit: bool
// 恢复到未选定状态
updateValue(dom.options, newMultiple ? [] : '', newMultiple);
}
} else if (isInit && defaultValue != null) { // 设置了 defaultValue 属性
} else if (isInit && defaultValue != null) {
// 设置了 defaultValue 属性
updateValue(dom.options, defaultValue, newMultiple);
}
}

View File

@ -15,7 +15,6 @@
import { Props } from '../utils/Interface';
// 值的优先级 value > children > defaultValue
function getInitValue(props: Props) {
const { value } = props;
@ -45,7 +44,7 @@ export function getTextareaPropsWithoutValue(dom: HTMLTextAreaElement, propertie
};
}
export function updateTextareaValue(dom: HTMLTextAreaElement, props: Props, isInit: boolean = false) {
export function updateTextareaValue(dom: HTMLTextAreaElement, props: Props, isInit = false) {
if (isInit) {
const initValue = getInitValue(props);
if (initValue !== '') {
@ -63,4 +62,3 @@ export function updateTextareaValue(dom: HTMLTextAreaElement, props: Props, isIn
}
}
}

View File

@ -19,22 +19,10 @@
*/
import { HorizonDom, HorizonSelect, Props } from '../utils/Interface';
import {
getInputPropsWithoutValue,
setInitInputValue,
updateInputValue,
} from './InputValueHandler';
import {
getOptionPropsWithoutValue,
} from './OptionValueHandler';
import {
getSelectPropsWithoutValue,
updateSelectValue,
} from './SelectValueHandler';
import {
getTextareaPropsWithoutValue,
updateTextareaValue,
} from './TextareaValueHandler';
import { getInputPropsWithoutValue, setInitInputValue, updateInputValue } from './InputValueHandler';
import { getOptionPropsWithoutValue } from './OptionValueHandler';
import { getSelectPropsWithoutValue, updateSelectValue } from './SelectValueHandler';
import { getTextareaPropsWithoutValue, updateTextareaValue } from './TextareaValueHandler';
// 获取元素除了被代理的值以外的属性
function getPropsWithoutValue(type: string, dom: HorizonDom, props: Props) {
@ -86,8 +74,4 @@ function updateValue(type: string, dom: HorizonDom, props: Props) {
}
}
export {
getPropsWithoutValue,
setInitValue,
updateValue,
};
export { getPropsWithoutValue, setInitValue, updateValue };

View File

@ -16,10 +16,7 @@
/**
*
*/
import {
allDelegatedHorizonEvents,
allDelegatedNativeEvents,
} from './EventHub';
import { allDelegatedHorizonEvents, allDelegatedNativeEvents } from './EventHub';
import { isDocument } from '../dom/utils/Common';
import { getNearestVNode, getNonDelegatedListenerMap } from '../dom/DOMInternalKeys';
import { asyncUpdates, runDiscreteUpdates } from '../renderer/TreeBuilder';
@ -27,11 +24,7 @@ import { handleEventMain } from './HorizonEventMain';
import { decorateNativeEvent } from './EventWrapper';
import { VNode } from '../renderer/vnode/VNode';
const listeningMarker =
'_horizonListening' +
Math.random()
.toString(36)
.slice(4);
const listeningMarker = '_horizonListening' + Math.random().toString(36).slice(4);
// 触发委托事件
function triggerDelegatedEvent(

View File

@ -40,7 +40,7 @@ export class WrappedEvent {
stopPropagation: () => void;
preventDefault: () => void;
propagationStopped = false
propagationStopped = false;
isPropagationStopped = (): boolean => this.propagationStopped;
// 适配Keyboard键盘事件该函数不能由合成事件调用
@ -53,7 +53,7 @@ export class WrappedEvent {
this[name] = nativeEvent[name];
if (name === 'getModifierState') {
const keyBoardEvent = nativeEvent as KeyboardEvent;
this.getModifierState = (keyArg) => keyBoardEvent.getModifierState(keyArg);
this.getModifierState = keyArg => keyBoardEvent.getModifierState(keyArg);
}
}
// stopPropagation和preventDefault 必须通过Event实例调用

View File

@ -87,4 +87,3 @@ function controlInputValue(inputDom: HTMLInputElement, props: Props) {
updateInputValue(inputDom, props);
}
}

View File

@ -78,11 +78,7 @@ function getChangeListeners(
if (shouldTriggerChangeEvent(targetDom, nativeEvtName)) {
recordChangeEventTargets(target);
const event = decorateNativeEvent(
'onChange',
'change',
nativeEvt,
);
const event = decorateNativeEvent('onChange', 'change', nativeEvt);
return getListenersFromTree(vNode, 'onChange', event, EVENT_TYPE_ALL);
}
@ -95,7 +91,7 @@ function getCommonListeners(
vNode: null | VNode,
nativeEvent: AnyNativeEvent,
target: null | EventTarget,
isCapture: boolean,
isCapture: boolean
): ListenerUnitList {
const horizonEvtName = transformToHorizonEvent(nativeEvtName);
@ -117,12 +113,7 @@ function getCommonListeners(
}
const horizonEvent = decorateNativeEvent(horizonEvtName, nativeEvtName, nativeEvent);
return getListenersFromTree(
vNode,
horizonEvtName,
horizonEvent,
isCapture ? EVENT_TYPE_CAPTURE : EVENT_TYPE_BUBBLE,
);
return getListenersFromTree(vNode, horizonEvtName, horizonEvent, isCapture ? EVENT_TYPE_CAPTURE : EVENT_TYPE_BUBBLE);
}
// 按顺序执行事件队列
@ -145,27 +136,16 @@ function triggerHorizonEvents(
nativeEvtName: string,
isCapture: boolean,
nativeEvent: AnyNativeEvent,
vNode: VNode | null,
vNode: VNode | null
) {
const target = nativeEvent.target || nativeEvent.srcElement!;
// 触发普通委托事件
let listenerList: ListenerUnitList = getCommonListeners(
nativeEvtName,
vNode,
nativeEvent,
target,
isCapture,
);
let listenerList: ListenerUnitList = getCommonListeners(nativeEvtName, vNode, nativeEvent, target, isCapture);
// 触发特殊handler委托事件
if (!isCapture && horizonEventToNativeMap.get('onChange')!.includes(nativeEvtName)) {
const changeListeners = getChangeListeners(
nativeEvtName,
nativeEvent,
vNode,
target
);
const changeListeners = getChangeListeners(nativeEvtName, nativeEvent, vNode, target);
if (changeListeners.length) {
listenerList = listenerList.concat(changeListeners);
}
@ -175,7 +155,6 @@ function triggerHorizonEvents(
processListeners(listenerList);
}
// 其他事件正在执行中标记
let isInEventsExecution = false;
@ -185,7 +164,7 @@ export function handleEventMain(
isCapture: boolean,
nativeEvent: AnyNativeEvent,
vNode: null | VNode,
targetDom: EventTarget,
targetDom: EventTarget
): void {
let startVNode = vNode;
if (startVNode !== null) {

View File

@ -1,4 +1,3 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
@ -16,7 +15,6 @@
export function isInputElement(dom?: HTMLElement): boolean {
return dom instanceof HTMLInputElement || dom instanceof HTMLTextAreaElement;
}
export function setPropertyWritable(obj, propName) {

View File

@ -56,8 +56,8 @@ function mergeDefault(sourceObj, defaultObj) {
function buildElement(isClone, type, setting, children) {
// setting中的值优先级最高clone情况下从 type 中取值,创建情况下直接赋值为 null
const key = (setting && setting.key !== undefined) ? String(setting.key) : (isClone ? type.key : null);
const ref = (setting && setting.ref !== undefined) ? setting.ref : (isClone ? type.ref : null);
const key = setting && setting.key !== undefined ? String(setting.key) : isClone ? type.key : null;
const ref = setting && setting.ref !== undefined ? setting.ref : isClone ? type.ref : null;
const props = isClone ? { ...type.props } : {};
let vNode = isClone ? type.belongClassVNode : getProcessingClassVNode();

View File

@ -54,7 +54,7 @@ export const helper = {
return { name: HookName.RefHook, hIndex, value: (state as Ref<any>).current };
} else if (isEffectHook(state)) {
const name =
state.effectConstant == EffectConstant.LayoutEffect || (EffectConstant.LayoutEffect | EffectConstant.DepsChange)
state.effectConstant == EffectConstant.LayoutEffect || EffectConstant.LayoutEffect | EffectConstant.DepsChange
? HookName.LayoutEffectHook
: HookName.EffectHook;
return { name, hIndex, value: (state as Effect).effect };

View File

@ -19,7 +19,7 @@ import { createContext } from '../../renderer/components/context/CreateContext';
import { createElement } from '../../external/JSXElement';
import { BoundActionCreator } from './redux';
import { ReduxAction } from './redux';
import { ReduxStoreHandler } from '../store/StoreHandler'
import { ReduxStoreHandler } from '../store/StoreHandler';
const DefaultContext = createContext(null);
type Context = typeof DefaultContext;
@ -44,7 +44,7 @@ export function createStoreHook(context: Context) {
}
export function createSelectorHook(context: Context): (selector?: (any) => any) => any {
const store = (createStoreHook(context)() as unknown) as ReduxStoreHandler;
const store = createStoreHook(context)() as unknown as ReduxStoreHandler;
return function (selector = state => state) {
const [b, fr] = useState(false);
@ -60,7 +60,7 @@ export function createSelectorHook(context: Context): (selector?: (any) => any)
}
export function createDispatchHook(context: Context): () => BoundActionCreator {
const store = (createStoreHook(context)() as unknown) as ReduxStoreHandler;
const store = createStoreHook(context)() as unknown as ReduxStoreHandler;
return function () {
return action => {
store.dispatch(action);
@ -120,7 +120,7 @@ export function connect(
function Wrapper(props) {
const [f, forceReload] = useState(true);
const store = (useStore() as unknown) as ReduxStoreHandler;
const store = useStore() as unknown as ReduxStoreHandler;
useEffect(() => {
const unsubscribe = store.subscribe(() => forceReload(!f));

View File

@ -17,7 +17,9 @@ import { ReduxAction, ReduxMiddleware } from './redux';
import { ReduxStoreHandler } from '../store/StoreHandler';
function createThunkMiddleware(extraArgument?: any): ReduxMiddleware {
return (store: ReduxStoreHandler) => (next: (action: ReduxAction) => any) => (
return (store: ReduxStoreHandler) =>
(next: (action: ReduxAction) => any) =>
(
action:
| ReduxAction
| ((dispatch: (action: ReduxAction) => void, store: ReduxStoreHandler, extraArgument?: any) => any)

View File

@ -17,13 +17,12 @@ import {IObserver} from './Observer';
/**
* Observer
*
*/
export class HooklessObserver implements IObserver {
listeners: (() => void)[] = [];
useProp(key: string | symbol): void {
}
useProp(key: string | symbol): void {}
addListener(listener: () => void) {
this.listeners.push(listener);
@ -46,12 +45,9 @@ export class HooklessObserver implements IObserver {
});
}
triggerUpdate(vNode): void {
}
triggerUpdate(vNode): void {}
allChange(): void {
}
allChange(): void {}
clearByVNode(vNode): void {
}
clearByVNode(vNode): void {}
}

View File

@ -109,7 +109,7 @@ export class Observer implements IObserver {
}
allChange(): void {
let keyIt = this.keyVNodes.keys();
const keyIt = this.keyVNodes.keys();
let keyItem = keyIt.next();
while (!keyItem.done) {
this.setProp(keyItem.value);

View File

@ -42,8 +42,8 @@ export function get(rawObj: object, key: string | symbol, receiver: any, singleL
observer.watchers[prop].push(handler);
return () => {
observer.watchers[prop] = observer.watchers[prop].filter(cb => cb !== handler);
}
}
};
};
}
if (key === 'addListener') {

View File

@ -14,7 +14,6 @@
*/
export interface IObserver {
useProp: (key: string | symbol) => void;
addListener: (listener: () => void) => void;

View File

@ -38,18 +38,13 @@ function consoleError(error: any): void {
}
}
function handleRootError(
error: any,
) {
function handleRootError(error: any) {
// 注意:如果根节点抛出错误,不会销毁整棵树,只打印日志,抛出异常。
setRootThrowError(error);
consoleError(error);
}
function createClassErrorUpdate(
vNode: VNode,
error: any,
): Update {
function createClassErrorUpdate(vNode: VNode, error: any): Update {
const update = newUpdate();
update.type = UpdateState.Error;
@ -78,13 +73,10 @@ function createClassErrorUpdate(
return update;
}
function isPromise(error: any): error is PromiseType<any> {
return error !== null && typeof error === 'object' && typeof error.then === 'function'
return error !== null && typeof error === 'object' && typeof error.then === 'function';
}
// 处理capture和bubble阶段抛出的错误
export function handleRenderThrowError(
sourceVNode: VNode,
error: any,
) {
export function handleRenderThrowError(sourceVNode: VNode, error: any) {
// vNode抛出了异常标记Interrupted中断
FlagUtils.markInterrupted(sourceVNode);
// dirtyNodes 不再有效
@ -117,10 +109,8 @@ export function handleRenderThrowError(
const instance = vNode.realNode;
if (
(vNode.flags & DidCapture) === InitFlag &&
(
typeof ctor.getDerivedStateFromError === 'function' ||
(instance !== null && typeof instance.componentDidCatch === 'function')
)
(typeof ctor.getDerivedStateFromError === 'function' ||
(instance !== null && typeof instance.componentDidCatch === 'function'))
) {
FlagUtils.markShouldCapture(vNode);
@ -155,7 +145,6 @@ function triggerUpdate(vNode, state) {
}
}
// 处理submit阶段的异常
export function handleSubmitError(vNode: VNode, error: any) {
if (vNode.tag === TreeRoot) {
@ -169,20 +158,19 @@ export function handleSubmitError(vNode: VNode, error: any) {
if (node.tag === TreeRoot) {
handleRootError(error);
return;
} else if (node.tag === ClassComponent) { // 只有 class 组件才可以成为错误边界组件
} else if (node.tag === ClassComponent) {
// 只有 class 组件才可以成为错误边界组件
const ctor = node.type;
const instance = node.realNode;
if (
typeof ctor.getDerivedStateFromError === 'function' ||
typeof instance.componentDidCatch === 'function'
) {
if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function') {
const getDerivedStateFromError = node.type.getDerivedStateFromError;
if (typeof getDerivedStateFromError === 'function') {
// 打印错误
consoleError(error);
const retState = getDerivedStateFromError(error);
if (retState) { // 有返回值
if (retState) {
// 有返回值
// 触发更新
triggerUpdate(node, retState);
}
@ -190,7 +178,8 @@ export function handleSubmitError(vNode: VNode, error: any) {
// 处理componentDidCatch
if (instance !== null && typeof instance.componentDidCatch === 'function') {
if (typeof getDerivedStateFromError !== 'function') { // 没有getDerivedStateFromError
if (typeof getDerivedStateFromError !== 'function') {
// 没有getDerivedStateFromError
// 打印错误
consoleError(error);
}

View File

@ -1,4 +1,3 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*

View File

@ -16,30 +16,15 @@
import type { VNode } from './Types';
import type { Update } from './UpdateHandler';
import {
asyncUpdates,
syncUpdates,
runDiscreteUpdates,
launchUpdateFromVNode,
} from './TreeBuilder';
import { asyncUpdates, syncUpdates, runDiscreteUpdates, launchUpdateFromVNode } from './TreeBuilder';
import { runAsyncEffects } from './submit/HookEffectHandler';
import { Callback, newUpdate, pushUpdate } from './UpdateHandler';
export { createVNode, createTreeRootVNode } from './vnode/VNodeCreator';
export { createPortal } from './components/CreatePortal';
export {
asyncUpdates,
syncUpdates,
runDiscreteUpdates,
runAsyncEffects,
};
export { asyncUpdates, syncUpdates, runDiscreteUpdates, runAsyncEffects };
export function startUpdate(
element: any,
treeRoot: VNode,
callback?: Callback,
) {
export function startUpdate(element: any, treeRoot: VNode, callback?: Callback) {
const update: Update = newUpdate();
update.content = { element };
@ -58,4 +43,3 @@ export function getFirstCustomDom(treeRoot?: VNode | null): Element | Text | nul
}
return null;
}

View File

@ -45,12 +45,7 @@ import {
isExecuting,
setExecuteMode,
} from './ExecuteMode';
import {
resetContext,
resetNamespaceCtx,
setContext,
setNamespaceCtx,
} from './ContextSaver';
import { resetContext, resetNamespaceCtx, setContext, setNamespaceCtx } from './ContextSaver';
import {
updateChildShouldUpdate,
updateParentsChildShouldUpdate,
@ -110,7 +105,8 @@ function bubbleVNode(vNode: VNode): void {
do {
const parent = node.parent;
if ((node.flags & Interrupted) === InitFlag) { // vNode没有抛出异常
if ((node.flags & Interrupted) === InitFlag) {
// vNode没有抛出异常
componentRenders[node.tag].bubbleRender(node);
// 设置node的childShouldUpdate属性
@ -133,7 +129,8 @@ function bubbleVNode(vNode: VNode): void {
}
const siblingVNode = node.next;
if (siblingVNode !== null) { // 有兄弟vNode
if (siblingVNode !== null) {
// 有兄弟vNode
processing = siblingVNode;
return;
}
@ -244,7 +241,8 @@ function buildVNodeTree(treeRoot: VNode) {
// 清空toUpdateNodes
treeRoot.toUpdateNodes.clear();
if (startVNode.tag !== TreeRoot) { // 不是根节点
if (startVNode.tag !== TreeRoot) {
// 不是根节点
// 设置namespace用于createElement
let parent = startVNode.parent;
while (parent !== null) {
@ -290,7 +288,8 @@ function buildVNodeTree(treeRoot: VNode) {
handleError(treeRoot, thrownValue);
}
}
if (startVNode.tag !== TreeRoot) { // 不是根节点
if (startVNode.tag !== TreeRoot) {
// 不是根节点
// 恢复父节点的context
resetTreeContext(startVNode);
}
@ -365,9 +364,7 @@ function renderFromRoot(treeRoot) {
export function tryRenderFromRoot(treeRoot: VNode) {
if (treeRoot.shouldUpdate && treeRoot.task === null) {
// 任务放进queue但是调度开始还是异步的
treeRoot.task = pushRenderCallback(
renderFromRoot.bind(null, treeRoot),
);
treeRoot.task = pushRenderCallback(renderFromRoot.bind(null, treeRoot));
}
}
@ -387,8 +384,11 @@ export function launchUpdateFromVNode(vNode: VNode) {
// 保存待刷新的节点
treeRoot.toUpdateNodes?.add(vNode);
if (checkMode(BySync) && // 非批量
!checkMode(InRender)) { // 不是渲染阶段触发
if (
checkMode(BySync) && // 非批量
!checkMode(InRender)
) {
// 不是渲染阶段触发
// 业务直接调用Horizon.render的时候会进入这个分支同步渲染。
// 不能改成下面的异步,否则会有时序问题,因为业务可能会依赖这个渲染的完成。

View File

@ -53,13 +53,7 @@ export function pushUpdate(vNode: VNode, update: Update) {
}
// 根据update获取新的state
function calcState(
vNode: VNode,
update: Update,
inst: any,
oldState: any,
props: any,
): any {
function calcState(vNode: VNode, update: Update, inst: any, oldState: any, props: any): any {
switch (update.type) {
case UpdateState.Override:
const content = update.content;
@ -73,9 +67,7 @@ function calcState(
case UpdateState.Update:
const updateContent = update.content;
const newState = typeof updateContent === 'function' ? updateContent.call(inst, oldState, props) : updateContent;
return (newState === null || newState === undefined)
? oldState
: { ...oldState, ...newState };
return newState === null || newState === undefined ? oldState : { ...oldState, ...newState };
default:
return oldState;
}
@ -118,7 +110,6 @@ export function processUpdates(vNode: VNode, inst: any, props: any): void {
calcUpdates(vNode, props, inst, toProcessUpdates);
}
}
}
export function pushForceUpdate(vNode: VNode) {

View File

@ -16,11 +16,7 @@
import { TYPE_PORTAL } from '../../external/JSXElementType';
import type { PortalType } from '../Types';
export function createPortal(
children: any,
realNode: any,
key: string = '',
): PortalType {
export function createPortal(children: any, realNode: any, key = ''): PortalType {
return {
vtype: TYPE_PORTAL,
key: key == '' ? '' : '' + key,

View File

@ -59,7 +59,7 @@ function lazyLoader<T>(lazyContent: LazyContent<T>): any {
lazyContent._status = LayStatus.Rejected;
lazyContent._value = error;
}
},
}
);
}
if (lazyContent._status === LayStatus.Fulfilled) {

View File

@ -35,7 +35,7 @@ function collectDeps<T>(vNode: VNode, context: ContextType<T>) {
}
}
export function getNewContext<T>(vNode: VNode, ctx: ContextType<T>, isUseContext: boolean = false): T {
export function getNewContext<T>(vNode: VNode, ctx: ContextType<T>, isUseContext = false): T {
// 如果来自于useContext则需要在函数组件中调用
if (isUseContext && getHookStage() === null) {
throwNotInFuncError();

View File

@ -24,13 +24,7 @@ import {
createPortalVNode,
createDomTextVNode,
} from '../vnode/VNodeCreator';
import {
isSameType,
getIteratorFn,
isTextType,
isIteratorType,
isObjectType,
} from './DiffTools';
import { isSameType, getIteratorFn, isTextType, isIteratorType, isObjectType } from './DiffTools';
import { travelChildren } from '../vnode/VNodeUtils';
import { markVNodePath } from '../utils/vNodePath';
@ -120,10 +114,12 @@ function getNodeType(newChild: any): string | null {
function setVNodeAdditionFlag(newNode: VNode, lastPosition: number): number {
let position = lastPosition;
if (newNode.isCreated || newNode.eIndex < lastPosition) { // 位置 小于 上一个复用的位置
if (newNode.isCreated || newNode.eIndex < lastPosition) {
// 位置 小于 上一个复用的位置
// 标记为新增
FlagUtils.setAddition(newNode);
} else { // 复用
} else {
// 复用
position = newNode.eIndex;
}
@ -206,15 +202,16 @@ function transRightChildrenToArray(child) {
return rightChildrenArray;
}
function transLeftChildrenToMap(
startChild: VNode,
rightEndVNode: VNode | null,
): Map<string | number, VNode> {
function transLeftChildrenToMap(startChild: VNode, rightEndVNode: VNode | null): Map<string | number, VNode> {
const leftChildrenMap: Map<string | number, VNode> = new Map();
travelChildren(startChild, node => {
travelChildren(
startChild,
node => {
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
}, node => node === rightEndVNode);
},
node => node === rightEndVNode
);
return leftChildrenMap;
}
@ -235,11 +232,7 @@ function getOldNodeFromMap(nodeMap: Map<string | number, VNode>, newIdx: number,
}
// diff数组类型的节点核心算法
function diffArrayNodesHandler(
parentNode: VNode,
firstChild: VNode | null,
newChildren: Array<any>,
): VNode | null {
function diffArrayNodesHandler(parentNode: VNode, firstChild: VNode | null, newChildren: Array<any>): VNode | null {
let resultingFirstChild: VNode | null = null;
let prevNewNode: VNode | null = null;
@ -366,13 +359,14 @@ function diffArrayNodesHandler(
// 4. 新节点还有一部分,但是老节点已经没有了
if (oldNode === null) {
let isDirectAdd = false;
// TODO: 是否可以扩大至非dom类型节点
// 如果dom节点在上次添加前没有节点说明本次添加时可以直接添加到最后不需要通过 getSiblingDom 函数找到 before 节点
if (parentNode.tag === DomComponent &&
if (
parentNode.tag === DomComponent &&
parentNode.oldProps?.children?.length === 0 &&
rightIdx - leftIdx === newChildren.length) {
rightIdx - leftIdx === newChildren.length
) {
isDirectAdd = true;
}
const isAddition = parentNode.tag === DomPortal || !parentNode.isCreated;
@ -424,7 +418,8 @@ function diffArrayNodesHandler(
const eIndex = newNode.eIndex;
eIndexes.push(eIndex);
last = eIndexes[result[result.length - 1]];
if (eIndex > last || last === undefined) { // 大的 eIndex直接放在最后
if (eIndex > last || last === undefined) {
// 大的 eIndex直接放在最后
preIndex[i] = result[result.length - 1];
result.push(i);
} else {
@ -500,7 +495,7 @@ function setVNodesCIndex(startChild: VNode | null, startIdx: number) {
function diffIteratorNodesHandler(
parentNode: VNode,
firstChild: VNode | null,
newChildrenIterable: Iterable<any>,
newChildrenIterable: Iterable<any>
): VNode | null {
const iteratorFn = getIteratorFn(newChildrenIterable);
const iteratorObj = iteratorFn.call(newChildrenIterable);
@ -517,12 +512,7 @@ function diffIteratorNodesHandler(
}
// 新节点是字符串类型
function diffStringNodeHandler(
parentNode: VNode,
newChild: any,
firstChildVNode: VNode,
isComparing: boolean
) {
function diffStringNodeHandler(parentNode: VNode, newChild: any, firstChildVNode: VNode, isComparing: boolean) {
let newTextNode: VNode | null = null;
// 第一个vNode是Text则复用

View File

@ -35,9 +35,7 @@ export function setCurrentHook(hook: Hook<any, any> | null) {
}
export function throwNotInFuncError() {
throw Error(
'Hooks should be used inside function component.',
);
throw Error('Hooks should be used inside function component.');
}
// 新建一个hook并放到vNode.hooks中
@ -63,9 +61,8 @@ export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>)
// 原因1.比对hook的数量有没有变化非必要2.从上一次执行中的hook获取removeEffect
export function getCurrentHook(): Hook<any, any> {
const processingVNode = getProcessingVNode();
currentHook = currentHook !== null ?
getNextHook(currentHook, processingVNode.hooks) :
(processingVNode.hooks[0] || null);
currentHook =
currentHook !== null ? getNextHook(currentHook, processingVNode.hooks) : processingVNode.hooks[0] || null;
if (lastTimeHook !== null) {
lastTimeHook = getNextHook(lastTimeHook, processingVNode.oldHooks);

View File

@ -29,23 +29,16 @@ import {Ref, Trigger} from './HookType';
type BasicStateAction<S> = ((S) => S) | S;
type Dispatch<A> = (A) => void;
export function useContext<T>(
Context: ContextType<T>,
): T {
export function useContext<T>(Context: ContextType<T>): T {
const processingVNode = getProcessingVNode();
return getNewContext(processingVNode!, Context, true);
}
export function useState<S>(initialState: (() => S) | S,): [S, Dispatch<BasicStateAction<S>>] {
export function useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>] {
return useStateImpl(initialState);
}
export function useReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: (I) => S,
): [S, Trigger<A>] | void {
export function useReducer<S, I, A>(reducer: (S, A) => S, initialArg: I, init?: (I) => S): [S, Trigger<A>] | void {
return useReducerImpl(reducer, initialArg, init);
}
@ -53,38 +46,26 @@ export function useRef<T>(initialValue: T): Ref<T> {
return useRefImpl(initialValue);
}
export function useEffect(
create: () => (() => void) | void,
deps?: Array<any> | null,
): void {
export function useEffect(create: () => (() => void) | void, deps?: Array<any> | null): void {
return useEffectImpl(create, deps);
}
export function useLayoutEffect(
create: () => (() => void) | void,
deps?: Array<any> | null,
): void {
export function useLayoutEffect(create: () => (() => void) | void, deps?: Array<any> | null): void {
return useLayoutEffectImpl(create, deps);
}
export function useCallback<T>(
callback: T,
deps?: Array<any> | null,
): T {
export function useCallback<T>(callback: T, deps?: Array<any> | null): T {
return useCallbackImpl(callback, deps);
}
export function useMemo<T>(
create: () => T,
deps?: Array<any> | null,
): T {
export function useMemo<T>(create: () => T, deps?: Array<any> | null): T {
return useMemoImpl(create, deps);
}
export function useImperativeHandle<T>(
ref: { current: T | null } | ((inst: T | null) => any) | null | void,
create: () => T,
deps?: Array<any> | null,
deps?: Array<any> | null
): void {
return useImperativeHandleImpl(ref, create, deps);
}

View File

@ -15,11 +15,7 @@
import type { VNode } from '../Types';
import {
getLastTimeHook,
setLastTimeHook,
setCurrentHook, getNextHook
} from './BaseHook';
import { getLastTimeHook, setLastTimeHook, setCurrentHook, getNextHook } from './BaseHook';
import { HookStage, setHookStage } from './HookStage';
// hook对外入口
@ -27,7 +23,7 @@ export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
funcComp: (props: Props, arg: Arg) => any,
props: Props,
arg: Arg,
processing: VNode,
processing: VNode
) {
// 重置全局变量
resetGlobalVariable();
@ -67,4 +63,3 @@ function resetGlobalVariable() {
setLastTimeHook(null);
setCurrentHook(null);
}

View File

@ -13,11 +13,7 @@
* See the Mulan PSL v2 for more details.
*/
import {
createHook,
getCurrentHook,
throwNotInFuncError
} from './BaseHook';
import { createHook, getCurrentHook, throwNotInFuncError } from './BaseHook';
import { getHookStage, HookStage } from './HookStage';
import { isArrayEqual } from '../utils/compare';

View File

@ -13,12 +13,7 @@
* See the Mulan PSL v2 for more details.
*/
import {
createHook,
getCurrentHook,
getLastTimeHook,
throwNotInFuncError
} from './BaseHook';
import { createHook, getCurrentHook, getLastTimeHook, throwNotInFuncError } from './BaseHook';
import { FlagUtils } from '../vnode/VNodeFlags';
import { EffectConstant } from './EffectConstant';
import type { Effect, EffectList } from './HookType';
@ -26,7 +21,7 @@ import {getHookStage, HookStage} from './HookStage';
import { isArrayEqual } from '../utils/compare';
import { getProcessingVNode } from '../GlobalVar';
export function useEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null,): void {
export function useEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null): void {
// 异步触发的effect
useEffect(effectFunc, deps, EffectConstant.Effect);
}
@ -36,11 +31,7 @@ export function useLayoutEffectImpl(effectFunc: () => (() => void) | void, deps?
useEffect(effectFunc, deps, EffectConstant.LayoutEffect);
}
function useEffect(
effectFunc: () => (() => void) | void,
deps: Array<any> | void | null,
effectType: number
): void {
function useEffect(effectFunc: () => (() => void) | void, deps: Array<any> | void | null, effectType: number): void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();

View File

@ -21,7 +21,7 @@ import type {Ref} from './HookType';
export function useImperativeHandleImpl<R>(
ref: { current: R | null } | ((any) => any) | null | void,
func: () => R,
dependencies?: Array<any> | null,
dependencies?: Array<any> | null
): void {
const stage = getHookStage();
if (stage === null) {
@ -36,10 +36,7 @@ function isNotNull(object: any): boolean {
return object !== null && object !== undefined;
}
function effectFunc<R>(
func: () => R,
ref: Ref<R> | ((any) => any) | null,
): (() => void) | void {
function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (() => void) | void {
if (typeof ref === 'function') {
const value = func();
ref(value);

View File

@ -13,15 +13,11 @@
* See the Mulan PSL v2 for more details.
*/
import {
createHook,
getCurrentHook,
throwNotInFuncError
} from './BaseHook';
import { createHook, getCurrentHook, throwNotInFuncError } from './BaseHook';
import { getHookStage, HookStage } from './HookStage';
import { isArrayEqual } from '../utils/compare';
export function useMemoImpl<V>(fun: () => V, deps?: Array<any> | null,): V {
export function useMemoImpl<V>(fun: () => V, deps?: Array<any> | null): V {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();

View File

@ -137,7 +137,7 @@ function updateReducerHookState<S, A>(currentHookUpdates, currentHook, reducer):
// 计算stateValue值
function calculateNewState<S, A>(currentHookUpdates: Array<Update<S, A>>, currentHook, reducer: (S, A) => S) {
let reducerObj = currentHook.state;
const reducerObj = currentHook.state;
let state = reducerObj.stateValue;
// 循环遍历更新数组,计算新的状态值

View File

@ -30,9 +30,7 @@ import {
} from './class/ClassLifeCycleProcessor';
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
import { markRef } from './BaseComponent';
import {
processUpdates,
} from '../UpdateHandler';
import { processUpdates } from '../UpdateHandler';
import { setProcessingClassVNode } from '../GlobalVar';
import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator';
import { createChildrenByDiff } from '../diff/nodeDiffComparator';
@ -41,9 +39,7 @@ const emptyContextObj = {};
// 获取当前节点的context
export function getCurrentContext(clazz, processing: VNode) {
const context = clazz.contextType;
return typeof context === 'object' && context !== null
? getNewContext(processing, context)
: emptyContextObj;
return typeof context === 'object' && context !== null ? getNewContext(processing, context) : emptyContextObj;
}
// 挂载实例
@ -84,9 +80,7 @@ function createChildren(clazz: any, processing: VNode) {
const isCatchError = (processing.flags & DidCapture) === DidCapture;
// 按照已有规格如果捕获了错误却没有定义getDerivedStateFromError函数返回的child为null
const newElements = isCatchError && typeof clazz.getDerivedStateFromError !== 'function'
? null
: inst.render();
const newElements = isCatchError && typeof clazz.getDerivedStateFromError !== 'function' ? null : inst.render();
processing.child = createChildrenByDiff(processing, processing.child, newElements, !processing.isCreated);
return processing.child;
@ -136,7 +130,8 @@ export function captureRender(processing: VNode): VNode | null {
// 挂载新组件,一定会更新
mountInstance(ctor, processing, nextProps);
shouldUpdate = true;
} else { // 更新
} else {
// 更新
const newContext = getCurrentContext(ctor, processing);
// 子节点抛出异常时如果本class是个捕获异常的处理节点这时候oldProps是null所以需要使用props
@ -150,9 +145,7 @@ export function captureRender(processing: VNode): VNode | null {
processUpdates(processing, inst, nextProps);
// 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新
shouldUpdate = oldProps !== processing.props ||
inst.state !== processing.state ||
processing.isForceUpdate;
shouldUpdate = oldProps !== processing.props || inst.state !== processing.state || processing.isForceUpdate;
if (shouldUpdate) {
// derivedStateFromProps会修改nextState因此需要调用

View File

@ -36,4 +36,3 @@ export function captureRender(processing: VNode): VNode | null {
}
export function bubbleRender() {}

View File

@ -18,10 +18,7 @@ import type { VNode, ContextType, ProviderType } from '../Types';
import { isSame } from '../utils/compare';
import { ClassComponent, ContextProvider } from '../vnode/VNodeTags';
import { pushForceUpdate } from '../UpdateHandler';
import {
resetContext,
setContext,
} from '../ContextSaver';
import { resetContext, setContext } from '../ContextSaver';
import { travelVNodeTree } from '../vnode/VNodeUtils';
import { launchUpdateFromVNode } from '../TreeBuilder';
import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator';
@ -62,15 +59,20 @@ function handleContextChange(processing: VNode, context: ContextType<any>): void
let isMatch = false;
// 从vNode开始遍历
travelVNodeTree(vNode, node => {
travelVNodeTree(
vNode,
node => {
const depContexts = node.depContexts;
if (depContexts && depContexts.length) {
isMatch = matchDependencies(depContexts, context, node) ?? isMatch;
}
}, node =>
},
node =>
// 如果这是匹配的provider则不要更深入地扫描
node.tag === ContextProvider && node.type === processing.type
, processing, null);
node.tag === ContextProvider && node.type === processing.type,
processing,
null
);
// 找到了依赖context的子节点触发一次更新
if (isMatch) {
@ -117,4 +119,3 @@ export function captureRender(processing: VNode): VNode | null {
export function bubbleRender(processing: VNode) {
resetContext(processing);
}

View File

@ -16,28 +16,15 @@
import type { VNode } from '../Types';
import type { Props } from '../../dom/DOMOperator';
import {
getNamespaceCtx,
setNamespaceCtx,
resetNamespaceCtx,
} from '../ContextSaver';
import {
appendChildElement,
newDom,
initDomProps, getPropChangeList,
isTextChild,
} from '../../dom/DOMOperator';
import { getNamespaceCtx, setNamespaceCtx, resetNamespaceCtx } from '../ContextSaver';
import { appendChildElement, newDom, initDomProps, getPropChangeList, isTextChild } from '../../dom/DOMOperator';
import { FlagUtils } from '../vnode/VNodeFlags';
import { markRef } from './BaseComponent';
import { DomComponent, DomPortal, DomText } from '../vnode/VNodeTags';
import { travelVNodeTree } from '../vnode/VNodeUtils';
import { createChildrenByDiff } from '../diff/nodeDiffComparator';
function updateDom(
processing: VNode,
type: any,
newProps: Props,
) {
function updateDom(processing: VNode, type: any, newProps: Props) {
// 如果oldProps !== newProps意味着存在更新并且需要处理其相关的副作用
const oldProps = processing.oldProps;
if (oldProps === newProps) {
@ -47,12 +34,7 @@ function updateDom(
const dom: Element = processing.realNode;
const changeList = getPropChangeList(
dom,
type,
oldProps,
newProps,
);
const changeList = getPropChangeList(dom, type, oldProps, newProps);
// 输入类型的直接标记更新
if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') {
@ -74,11 +56,7 @@ export function bubbleRender(processing: VNode) {
const newProps = processing.props;
if (!processing.isCreated && processing.realNode != null) {
// 更新dom属性
updateDom(
processing,
type,
newProps,
);
updateDom(processing, type, newProps);
if (processing.oldRef !== processing.ref) {
FlagUtils.markRef(processing);
@ -87,25 +65,25 @@ export function bubbleRender(processing: VNode) {
const parentNamespace = getNamespaceCtx();
// 创建dom
const dom = newDom(
type,
newProps,
parentNamespace,
processing,
);
const dom = newDom(type, newProps, parentNamespace, processing);
// 把dom类型的子节点append到parent dom中
const vNode = processing.child;
if (vNode !== null) {
// 向下递归它的子节点,查找所有终端节点。
travelVNodeTree(vNode, node => {
travelVNodeTree(
vNode,
node => {
if (node.tag === DomComponent || node.tag === DomText) {
appendChildElement(dom, node.realNode);
}
}, node =>
},
node =>
// 已经append到父节点或者是DomPortal都不需要处理child了
node.tag === DomComponent || node.tag === DomText || node.tag === DomPortal
, processing, null);
node.tag === DomComponent || node.tag === DomText || node.tag === DomPortal,
processing,
null
);
}
processing.realNode = dom;

View File

@ -26,25 +26,24 @@ export function captureRender(): VNode | null {
export function bubbleRender(processing: VNode) {
const newText = processing.props;
if (!processing.isCreated && processing.realNode != null) { // 更新
if (!processing.isCreated && processing.realNode != null) {
// 更新
const oldText = processing.oldProps;
// 如果文本不同,将其标记为更新
if (oldText !== newText) {
FlagUtils.markUpdate(processing);
}
} else { // 初始化
} else {
// 初始化
if (typeof newText !== 'string') {
// 如果存在bug可能出现这种情况
throwIfTrue(
processing.realNode === null,
'We must have new text for new mounted node. This error is likely ' +
'caused by a bug in Horizon. Please file an issue.',
'caused by a bug in Horizon. Please file an issue.'
);
}
// 获得对应节点
processing.realNode = newTextDom(
newText,
processing,
);
processing.realNode = newTextDom(newText, processing);
}
}

View File

@ -21,4 +21,3 @@ export function captureRender(processing: VNode): VNode | null {
}
export function bubbleRender() {}

View File

@ -26,14 +26,11 @@ import { createChildrenByDiff } from '../diff/nodeDiffComparator';
// 在useState, useReducer的时候会触发state变化
let stateChange = false;
export function bubbleRender() {
}
export function bubbleRender() {}
// 判断children是否可以复用
function checkIfCanReuseChildren(processing: VNode) {
return !processing.isCreated &&
processing.oldProps === processing.props &&
!processing.isDepContextChange;
return !processing.isCreated && processing.oldProps === processing.props && !processing.isDepContextChange;
}
export function setStateChange(isUpdate) {
@ -44,11 +41,7 @@ export function isStateChange() {
return stateChange;
}
export function captureFunctionComponent(
processing: VNode,
funcComp: any,
nextProps: any,
) {
export function captureFunctionComponent(processing: VNode, funcComp: any, nextProps: any) {
// 函数组件内已完成异步动作
if (processing.isSuspended) {
// 由于首次被打断,应仍为首次渲染
@ -67,7 +60,7 @@ export function captureFunctionComponent(
processing.tag === ForwardRef ? funcComp.render : funcComp,
nextProps,
processing.tag === ForwardRef ? processing.ref : undefined,
processing,
processing
);
// 这里需要判断是否可以复用因为函数组件比起其他组件多了context、stateChange、或者store改变了 三个因素
@ -86,15 +79,7 @@ export function captureFunctionComponent(
export function captureRender(processing: VNode): VNode | null {
const Component = processing.type;
const unresolvedProps = processing.props;
const resolvedProps =
processing.isLazyComponent
? mergeDefaultProps(Component, unresolvedProps)
: unresolvedProps;
const resolvedProps = processing.isLazyComponent ? mergeDefaultProps(Component, unresolvedProps) : unresolvedProps;
return captureFunctionComponent(
processing,
Component,
resolvedProps,
);
return captureFunctionComponent(processing, Component, resolvedProps);
}

View File

@ -17,12 +17,7 @@ import type { VNode } from '../Types';
import { FlagUtils } from '../vnode/VNodeFlags';
import { getLazyVNodeTag } from '../vnode/VNodeCreator';
import {
ClassComponent,
ForwardRef,
FunctionComponent,
MemoComponent,
} from '../vnode/VNodeTags';
import { ClassComponent, ForwardRef, FunctionComponent, MemoComponent } from '../vnode/VNodeTags';
import { throwIfTrue } from '../utils/throwIfTrue';
import { captureFunctionComponent } from './FunctionComponent';
import { captureRender as captureClassComponent } from './ClassComponent';
@ -51,11 +46,7 @@ export function mergeDefaultProps(Component: any, props: object): object {
return props;
}
function captureLazyComponent(
processing,
lazyComponent,
shouldUpdate,
) {
function captureLazyComponent(processing, lazyComponent, shouldUpdate) {
if (!processing.isCreated) {
// 每次加载lazy都当作mount来处理
processing.isCreated = true;
@ -89,7 +80,7 @@ function captureLazyComponent(
'Element type is invalid. Received a promise that resolves to: %s. ' +
'Lazy element type must resolve to a class or function.%s',
Component,
'',
''
);
return null;
}

View File

@ -17,12 +17,7 @@ import type { VNode, PromiseType } from '../Types';
import { FlagUtils, Interrupted } from '../vnode/VNodeFlags';
import { onlyUpdateChildVNodes, updateVNode, createFragmentVNode } from '../vnode/VNodeCreator';
import {
ClassComponent,
ForwardRef,
FunctionComponent,
SuspenseComponent,
} from '../vnode/VNodeTags';
import { ClassComponent, ForwardRef, FunctionComponent, SuspenseComponent } from '../vnode/VNodeTags';
import { pushForceUpdate } from '../UpdateHandler';
import { launchUpdateFromVNode, tryRenderFromRoot } from '../TreeBuilder';
import { updateShouldUpdateOfTree } from '../vnode/VNodeShouldUpdate';
@ -141,11 +136,7 @@ function updateFallback(processing: VNode): Array<VNode> | VNode | null {
}
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | VNode | null {
if (
!processing.isCreated &&
processing.oldProps === processing.props &&
!shouldUpdate
) {
if (!processing.isCreated && processing.oldProps === processing.props && !shouldUpdate) {
if (processing.suspenseState.childStatus === SuspenseChildStatus.ShowFallback) {
// 当显示fallback时suspense的子组件要更新
return updateFallback(processing);
@ -158,8 +149,9 @@ export function captureRender(processing: VNode, shouldUpdate: boolean): Array<V
export function bubbleRender(processing: VNode) {
const { childStatus, oldChildStatus } = processing.suspenseState;
if (childStatus === SuspenseChildStatus.ShowFallback
|| (!processing.isCreated && oldChildStatus === SuspenseChildStatus.ShowFallback)
if (
childStatus === SuspenseChildStatus.ShowFallback ||
(!processing.isCreated && oldChildStatus === SuspenseChildStatus.ShowFallback)
) {
FlagUtils.markUpdate(processing);
}
@ -183,7 +175,6 @@ export function handleSuspenseChildThrowError(parent: VNode, processing: VNode,
}
vNode.suspenseState.promiseSet.add(promise);
// 移除生命周期flag 和 中断flag
FlagUtils.removeLifecycleEffectFlags(processing);
FlagUtils.removeFlag(processing, Interrupted);

View File

@ -32,7 +32,7 @@ function updateTreeRoot(processing) {
processing.isCreated || updates === null,
'If the root does not have an updates, we should have already ' +
'bailed out. This error is likely caused by a bug. Please ' +
'file an issue.',
'file an issue.'
);
const newProps = processing.props;

View File

@ -17,12 +17,7 @@ import type { VNode } from '../../Types';
import type { Callback } from '../../UpdateHandler';
import { shallowCompare } from '../../utils/compare';
import {
pushUpdate,
newUpdate,
UpdateState,
processUpdates,
} from '../../UpdateHandler';
import { pushUpdate, newUpdate, UpdateState, processUpdates } from '../../UpdateHandler';
import { launchUpdateFromVNode } from '../../TreeBuilder';
import { FlagUtils } from '../../vnode/VNodeFlags';
import { getCurrentContext } from '../ClassComponent';
@ -31,7 +26,7 @@ import { PureComponent } from '../../components/BaseClassComponent';
export function callDerivedStateFromProps(
processing: VNode,
getDerivedStateFromProps: (props: object, state: object) => object,
nextProps: object,
nextProps: object
) {
if (getDerivedStateFromProps) {
const oldState = processing.state;
@ -40,9 +35,7 @@ export function callDerivedStateFromProps(
const newState = getDerivedStateFromProps(nextProps, oldState);
// 组件未返回state,需要返回旧的preState
processing.state = newState === null || newState === undefined
? oldState
: { ...oldState, ...newState };
processing.state = newState === null || newState === undefined ? oldState : { ...oldState, ...newState };
}
}
@ -68,7 +61,7 @@ export function callShouldComponentUpdate(
oldProps: object,
newProps: object,
newState: object,
newContext: object,
newContext: object
) {
const inst = processing.realNode;
@ -169,4 +162,3 @@ export function markComponentDidUpdate(processing: VNode) {
FlagUtils.markUpdate(processing);
}
}

View File

@ -44,9 +44,7 @@ import {
SuspenseComponent,
} from '../vnode/VNodeTags';
export {
BaseComponentRender,
};
export { BaseComponentRender };
export default {
[ClassComponent]: ClassComponentRender,

View File

@ -18,20 +18,15 @@
*/
import type { VNode } from '../Types';
import type {
Effect as HookEffect,
EffectList,
} from '../hooks/HookType';
import type { Effect as HookEffect, EffectList } from '../hooks/HookType';
import { runAsync } from '../taskExecutor/TaskExecutor';
import {
copyExecuteMode, InRender, setExecuteMode,changeMode
} from '../ExecuteMode';
import { copyExecuteMode, InRender, setExecuteMode, changeMode } from '../ExecuteMode';
import { EffectConstant } from '../hooks/EffectConstant';
let hookEffects: Array<HookEffect | VNode> = [];
let hookRemoveEffects: Array<HookEffect | VNode> = [];
// 是否正在异步调度effects
let isScheduling: boolean = false;
let isScheduling = false;
export function setSchedulingEffects(value) {
isScheduling = value;
@ -69,7 +64,7 @@ export function runAsyncEffects() {
// 调用effect destroy
const removeEffects = hookRemoveEffects;
hookRemoveEffects = [];
removeEffects.forEach((effect) => {
removeEffects.forEach(effect => {
const destroy = effect.removeEffect;
effect.removeEffect = undefined;
@ -85,7 +80,7 @@ export function runAsyncEffects() {
// 调用effect create
const createEffects = hookEffects;
hookEffects = [];
createEffects.forEach((effect) => {
createEffects.forEach(effect => {
try {
const create = effect.effect;
@ -106,14 +101,16 @@ export function callEffectRemove(vNode: VNode) {
const { removeEffect, effectConstant } = effect;
if (removeEffect !== undefined) {
if ((effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect) { // 如果是useEffect就异步调用
if ((effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect) {
// 如果是useEffect就异步调用
hookRemoveEffects.push(effect);
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
}
} else { // 是useLayoutEffect直接执行
} else {
// 是useLayoutEffect直接执行
removeEffect();
}
}

View File

@ -50,12 +50,7 @@ import {
callUseLayoutEffectRemove,
} from './HookEffectHandler';
import { handleSubmitError } from '../ErrorHandler';
import {
travelVNodeTree,
clearVNode,
isDomVNode,
getSiblingDom,
} from '../vnode/VNodeUtils';
import { travelVNodeTree, clearVNode, isDomVNode, getSiblingDom } from '../vnode/VNodeUtils';
import { shouldAutoFocus } from '../../dom/utils/Common';
function callComponentWillUnmount(vNode: VNode, instance: any) {
@ -67,13 +62,10 @@ function callComponentWillUnmount(vNode: VNode, instance: any) {
}
// 调用界面变化前的生命周期
function callBeforeSubmitLifeCycles(
vNode: VNode,
): void {
if (vNode.tag === ClassComponent && !vNode.isCreated) { // 调用instance.getSnapshotBeforeUpdate
const prevProps = vNode.isLazyComponent
? mergeDefaultProps(vNode.type, vNode.oldProps)
: vNode.oldProps;
function callBeforeSubmitLifeCycles(vNode: VNode): void {
if (vNode.tag === ClassComponent && !vNode.isCreated) {
// 调用instance.getSnapshotBeforeUpdate
const prevProps = vNode.isLazyComponent ? mergeDefaultProps(vNode.type, vNode.oldProps) : vNode.oldProps;
const prevState = vNode.oldState;
const instance = vNode.realNode;
@ -98,9 +90,7 @@ function callStateCallback(vNode: VNode, obj: any): void {
}
// 调用界面变化后的生命周期
function callAfterSubmitLifeCycles(
vNode: VNode,
): void {
function callAfterSubmitLifeCycles(vNode: VNode): void {
switch (vNode.tag) {
case FunctionComponent:
case ForwardRef: {
@ -116,17 +106,10 @@ function callAfterSubmitLifeCycles(
if (vNode.isCreated) {
instance.componentDidMount();
} else {
const prevProps =
vNode.isLazyComponent
? mergeDefaultProps(vNode.type, vNode.oldProps)
: vNode.oldProps;
const prevProps = vNode.isLazyComponent ? mergeDefaultProps(vNode.type, vNode.oldProps) : vNode.oldProps;
const prevState = vNode.oldState;
instance.componentDidUpdate(
prevProps,
prevState,
instance.__snapshotResult,
);
instance.componentDidUpdate(prevProps, prevState, instance.__snapshotResult);
}
}
@ -152,7 +135,9 @@ function callAfterSubmitLifeCycles(
}
function hideOrUnhideAllChildren(vNode, isHidden) {
travelVNodeTree(vNode, (node: VNode) => {
travelVNodeTree(
vNode,
(node: VNode) => {
const instance = node.realNode;
if (node.tag === DomComponent || node.tag === DomText) {
@ -162,7 +147,11 @@ function hideOrUnhideAllChildren(vNode, isHidden) {
unHideDom(node.tag, instance, node.props);
}
}
}, null, vNode, null);
},
null,
vNode,
null
);
}
function attachRef(vNode: VNode) {
@ -172,7 +161,7 @@ function attachRef(vNode: VNode) {
}
function detachRef(vNode: VNode, isOldRef?: boolean) {
let ref = (isOldRef ? vNode.oldRef : vNode.ref);
const ref = isOldRef ? vNode.oldRef : vNode.ref;
handleRef(vNode, ref, null);
}
@ -233,12 +222,17 @@ function unmountVNode(vNode: VNode): void {
// 卸载vNode递归遍历子vNode
function unmountNestedVNodes(vNode: VNode): void {
travelVNodeTree(vNode, (node) => {
travelVNodeTree(
vNode,
node => {
unmountVNode(node);
}, node =>
},
node =>
// 如果是DomPortal不需要遍历child
node.tag === DomPortal
, vNode, null);
node.tag === DomPortal,
vNode,
null
);
}
function submitAddition(vNode: VNode): void {
@ -269,11 +263,7 @@ function submitAddition(vNode: VNode): void {
insertOrAppendPlacementNode(vNode, before, parentDom);
}
function insertOrAppendPlacementNode(
node: VNode,
beforeDom: Element | null,
parent: Element | Container,
): void {
function insertOrAppendPlacementNode(node: VNode, beforeDom: Element | null, parent: Element | Container): void {
const { tag, realNode } = node;
if (isDomVNode(node)) {
@ -305,7 +295,9 @@ function unmountDomComponents(vNode: VNode): void {
// 这两个变量要一起更新
let currentParent;
travelVNodeTree(vNode, (node) => {
travelVNodeTree(
vNode,
node => {
if (!currentParentIsValid) {
let parent = node.parent;
let tag;
@ -333,14 +325,18 @@ function unmountDomComponents(vNode: VNode): void {
} else {
unmountVNode(node);
}
}, node =>
},
node =>
// 如果是dom不用再遍历child
node.tag === DomComponent || node.tag === DomText, vNode, (node) => {
node.tag === DomComponent || node.tag === DomText,
vNode,
node => {
if (node.tag === DomPortal) {
// 当离开portal需要重新设置parent
currentParentIsValid = false;
}
});
}
);
}
function submitClear(vNode: VNode): void {

View File

@ -21,27 +21,24 @@ import {handleSubmitError} from '../ErrorHandler';
import {
attachRef,
callAfterSubmitLifeCycles,
callBeforeSubmitLifeCycles, submitDeletion, submitAddition,
submitResetTextContent, submitUpdate, detachRef, submitClear,
callBeforeSubmitLifeCycles,
submitDeletion,
submitAddition,
submitResetTextContent,
submitUpdate,
detachRef,
submitClear,
} from './LifeCycleHandler';
import { tryRenderFromRoot } from '../TreeBuilder';
import {
InRender,
copyExecuteMode,
setExecuteMode,
changeMode,
} from '../ExecuteMode';
import {
isSchedulingEffects,
setSchedulingEffects,
} from './HookEffectHandler';
import { InRender, copyExecuteMode, setExecuteMode, changeMode } from '../ExecuteMode';
import { isSchedulingEffects, setSchedulingEffects } from './HookEffectHandler';
import { getStartVNode } from '../GlobalVar';
let rootThrowError = null;
// 防止死循环调用update
const LOOPING_UPDATE_LIMIT = 50;
let loopingUpdateCount: number = 0;
let loopingUpdateCount = 0;
let lastRoot: VNode | null = null;
export function submitToRender(treeRoot) {

View File

@ -21,7 +21,6 @@ let isMessageLoopRunning = false;
let browserCallback = null;
const { port1, port2 } = new MessageChannel();
export function isOverTime() {
return false;
}
@ -36,7 +35,8 @@ const callRenderTasks = () => {
// 执行callback
const hasMoreTask = browserCallback();
if (!hasMoreTask) { // 没有更多task
if (!hasMoreTask) {
// 没有更多task
isMessageLoopRunning = false;
browserCallback = null;
} else {
@ -49,7 +49,6 @@ const callRenderTasks = () => {
}
};
port1.onmessage = callRenderTasks;
export function requestBrowserCallback(callback) {

View File

@ -45,7 +45,7 @@ function callRenderQueue() {
try {
let callback;
while (callback = renderQueue.shift()) {
while ((callback = renderQueue.shift())) {
callback();
}

View File

@ -18,10 +18,7 @@
*/
import { Node } from '../taskExecutor/TaskQueue';
import {
requestBrowserCallback,
isOverTime,
} from './BrowserAsync';
import { requestBrowserCallback, isOverTime } from './BrowserAsync';
import { add, shift, first, remove } from './TaskQueue';
@ -60,7 +57,8 @@ function callTasks() {
if (task === first()) {
shift();
} else { // 执行任务中可能插入了新任务
} else {
// 执行任务中可能插入了新任务
remove(task);
}
} else {
@ -109,9 +107,4 @@ function cancelTask(task) {
task.callback = null;
}
export {
ImmediatePriority,
NormalPriority,
runAsync,
cancelTask,
};
export { ImmediatePriority, NormalPriority, runAsync, cancelTask };

View File

@ -57,8 +57,8 @@ export function shallowCompare(paramX: any, paramY: any): boolean {
return false;
}
return keysX.every((key, i) =>
Object.prototype.hasOwnProperty.call(paramY, key) && isSame(paramX[key], paramY[keysX[i]])
return keysX.every(
(key, i) => Object.prototype.hasOwnProperty.call(paramY, key) && isSame(paramX[key], paramY[keysX[i]])
);
}

View File

@ -19,7 +19,6 @@
import type { VNode } from './VNode';
export const InitFlag = /** */ 0;
// vNode节点的flags
export const DirectAddition = /** */ 1 << 0; // 在本次更新前入股父dom没有子节点说明本次可以直接添加至父节点不需要通过 getSiblingDom 找到 before 节点
@ -44,7 +43,8 @@ export class FlagUtils {
static removeLifecycleEffectFlags(node) {
node.flags &= ~LifecycleEffectArr;
}
static hasAnyFlag(node: VNode) { // 有标志位
static hasAnyFlag(node: VNode) {
// 有标志位
return node.flags !== InitFlag;
}
@ -97,4 +97,3 @@ export class FlagUtils {
node.flags |= Clear;
}
}

View File

@ -70,7 +70,8 @@ export function updateParentsChildShouldUpdate(vNode: VNode) {
let node = vNode.parent;
const isShouldUpdate = vNode.shouldUpdate || vNode.childShouldUpdate;
if (isShouldUpdate) { // 开始节点是shouldUpdate或childShouldUpdate
if (isShouldUpdate) {
// 开始节点是shouldUpdate或childShouldUpdate
// 更新从当前节点到根节点的childShouldUpdate为true
setParentsChildShouldUpdate(node);
} else {

View File

@ -125,20 +125,22 @@ export function isDomVNode(node: VNode) {
// 是容器类型的vNode
function isDomContainer(vNode: VNode): boolean {
return (
vNode.tag === DomComponent ||
vNode.tag === TreeRoot ||
vNode.tag === DomPortal
);
return vNode.tag === DomComponent || vNode.tag === TreeRoot || vNode.tag === DomPortal;
}
export function findDomVNode(vNode: VNode): VNode | null {
return travelVNodeTree(vNode, (node) => {
return travelVNodeTree(
vNode,
node => {
if (node.tag === DomComponent || node.tag === DomText) {
return node;
}
return null;
}, null, vNode, null);
},
null,
vNode,
null
);
}
export function findDOMByClassInst(inst) {

View File

@ -4,7 +4,8 @@
"libs/*"
],
"scripts": {
"lint": "eslint . --ext .ts",
"lint": "eslint . --ext .ts --fix",
"prettier": "prettier -w libs/**/*.ts",
"build": "rollup --config ./scripts/rollup/rollup.config.js",
"build:watch": "rollup --watch --config ./scripts/rollup/rollup.config.js",
"build:3rdLib": "node ./scripts/gen3rdLib.js build:3rdLib",