From d14122a5d3ef55ba66dfbabb9d196eace17e58c2 Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 20 Apr 2022 14:47:42 +0800 Subject: [PATCH] Match-id-c512ddd2eafdc01bfd6b07d73a3aead7828578e8 --- libs/horizon/src/dom/DOMInternalKeys.ts | 24 +++++-------- .../dom/DOMPropertiesHandler/StyleHandler.ts | 22 ++++++------ .../src/dom/validators/ValidateProps.ts | 2 +- libs/horizon/src/dom/valueHandler/index.ts | 2 +- libs/horizon/src/event/HorizonEventMain.ts | 17 +++++---- libs/horizon/src/renderer/vnode/VNodeUtils.ts | 35 ++++++------------- scripts/__tests__/DomTest/Attribute.test.js | 8 ++++- scripts/__tests__/DomTest/DomInput.test.js | 7 +++- 8 files changed, 54 insertions(+), 63 deletions(-) diff --git a/libs/horizon/src/dom/DOMInternalKeys.ts b/libs/horizon/src/dom/DOMInternalKeys.ts index 2f4ccb23..f389a0cf 100644 --- a/libs/horizon/src/dom/DOMInternalKeys.ts +++ b/libs/horizon/src/dom/DOMInternalKeys.ts @@ -49,23 +49,17 @@ export function getVNode(dom: Node|Container): VNode | null { // 用 DOM 对象,来寻找其对应或者说是最近父级的 vNode export function getNearestVNode(dom: Node): null | VNode { - let vNode = dom[INTERNAL_VNODE]; - if (vNode) { // 如果是已经被框架标记过的 DOM 节点,那么直接返回其 VNode 实例 - return vNode; + let domNode: Node | null = dom; + // 寻找当前节点及其所有祖先节点是否有标记VNODE + while (domNode) { + const vNode = domNode[INTERNAL_VNODE]; + if (vNode) { + return vNode; + } + domNode = domNode.parentNode; } - // 下面处理的是为被框架标记过的 DOM 节点,向上找其父节点是否被框架标记过 - let parentDom = dom.parentNode; - let nearVNode = null; - while (parentDom) { - vNode = parentDom[INTERNAL_VNODE]; - if (vNode) { - nearVNode = vNode; - break; - } - parentDom = parentDom.parentNode; - } - return nearVNode; + return null; } // 获取 vNode 上的属性相关信息 diff --git a/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts b/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts index 49429fbe..b93e1581 100644 --- a/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts +++ b/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts @@ -1,12 +1,12 @@ -function isNeedUnitCSS(propName: string) { - return !(noUnitCSS.includes(propName) - || propName.startsWith('borderImage') - || propName.startsWith('flex') - || propName.startsWith('gridRow') - || propName.startsWith('gridColumn') - || propName.startsWith('stroke') - || propName.startsWith('box') - || propName.endsWith('Opacity')); +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')); } /** @@ -38,9 +38,7 @@ export function setStyles(dom, styles) { Object.keys(styles).forEach((name) => { const styleVal = styles[name]; - const validStyleValue = adjustStyleValue(name, styleVal); - - style[name] = validStyleValue; + style[name] = adjustStyleValue(name, styleVal); }); } diff --git a/libs/horizon/src/dom/validators/ValidateProps.ts b/libs/horizon/src/dom/validators/ValidateProps.ts index 5616f342..9dcf4a23 100644 --- a/libs/horizon/src/dom/validators/ValidateProps.ts +++ b/libs/horizon/src/dom/validators/ValidateProps.ts @@ -6,7 +6,7 @@ const INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/; // 是内置元素 -export function isNativeElement(tagName: string, props: Object) { +export function isNativeElement(tagName: string, props: Record) { return !tagName.includes('-') && props.is === undefined; } diff --git a/libs/horizon/src/dom/valueHandler/index.ts b/libs/horizon/src/dom/valueHandler/index.ts index 88a35e5c..2e5b6da7 100644 --- a/libs/horizon/src/dom/valueHandler/index.ts +++ b/libs/horizon/src/dom/valueHandler/index.ts @@ -21,7 +21,7 @@ import { getTextareaPropsWithoutValue, updateTextareaValue, } from './TextareaValueHandler'; -import {getDomTag} from "../utils/Common"; +import {getDomTag} from '../utils/Common'; // 获取元素除了被代理的值以外的属性 function getPropsWithoutValue(type: string, dom: HorizonDom, properties: IProperty) { diff --git a/libs/horizon/src/event/HorizonEventMain.ts b/libs/horizon/src/event/HorizonEventMain.ts index 08e9f5d0..f0480724 100644 --- a/libs/horizon/src/event/HorizonEventMain.ts +++ b/libs/horizon/src/event/HorizonEventMain.ts @@ -16,8 +16,11 @@ import { decorateNativeEvent } from './customEvents/EventFactory'; import { getListenersFromTree } from './ListenerGetter'; import { shouldUpdateValue, updateControlledValue } from './ControlledValueUpdater'; import { asyncUpdates, runDiscreteUpdates } from '../renderer/Renderer'; -import { getExactNode } from '../renderer/vnode/VNodeUtils'; -import {ListenerUnitList} from './Types'; +import { findRoot } from '../renderer/vnode/VNodeUtils'; +import { ListenerUnitList } from './Types'; + +// web规范,鼠标右键key值 +const RIGHT_MOUSE_BUTTON = 2; // 获取事件触发的普通事件监听方法队列 function getCommonListeners( @@ -29,13 +32,13 @@ function getCommonListeners( ): ListenerUnitList { const name = CommonEventToHorizonMap[nativeEvtName]; const horizonEvtName = !name ? '' : `on${name[0].toUpperCase()}${name.slice(1)}`; // 例:dragEnd -> onDragEnd - + if (!horizonEvtName) { return []; } // 鼠标点击右键 - if (nativeEvent instanceof MouseEvent && nativeEvtName === 'click' && nativeEvent.button === 2) { + if (nativeEvent instanceof MouseEvent && nativeEvtName === 'click' && nativeEvent.button === RIGHT_MOUSE_BUTTON) { return []; } @@ -76,7 +79,7 @@ function getProcessListeners( vNode: VNode | null, nativeEvent: AnyNativeEvent, target, - isCapture: boolean + isCapture: boolean, ): ListenerUnitList { // 触发普通委托事件 let listenerList: ListenerUnitList = getCommonListeners( @@ -136,11 +139,11 @@ export function handleEventMain( isCapture: boolean, nativeEvent: AnyNativeEvent, vNode: null | VNode, - targetContainer: EventTarget, + targetDom: EventTarget, ): void { let startVNode = vNode; if (startVNode !== null) { - startVNode = getExactNode(startVNode, targetContainer); + startVNode = findRoot(startVNode, targetDom); if (!startVNode) { return; } diff --git a/libs/horizon/src/renderer/vnode/VNodeUtils.ts b/libs/horizon/src/renderer/vnode/VNodeUtils.ts index ef60b566..a586b922 100644 --- a/libs/horizon/src/renderer/vnode/VNodeUtils.ts +++ b/libs/horizon/src/renderer/vnode/VNodeUtils.ts @@ -31,7 +31,6 @@ export function travelVNodeTree( finishVNode: VNode, // 结束遍历节点,有时候和beginVNode不相同 handleWhenToParent: Function | null ): VNode | null { - const filter = childFilter === null; let node = beginVNode; while (true) { @@ -43,7 +42,7 @@ export function travelVNodeTree( // 找子节点 const childVNode = node.child; - if (childVNode !== null && (filter || !childFilter(node))) { + if (childVNode !== null && (childFilter === null || !childFilter(node))) { childVNode.parent = node; node = childVNode; continue; @@ -194,20 +193,6 @@ export function getSiblingDom(vNode: VNode): Element | null { } } -function isSameContainer( - container: Element, - targetContainer: EventTarget, -): boolean { - if (container === targetContainer) { - return true; - } - // 注释类型的节点 - if (isComment(container) && container.parentNode === targetContainer) { - return true; - } - return false; -} - function isPortalRoot(vNode, targetContainer) { if (vNode.tag === DomPortal) { let topVNode = vNode.parent; @@ -216,7 +201,7 @@ function isPortalRoot(vNode, targetContainer) { if (grandTag === TreeRoot || grandTag === DomPortal) { const topContainer = topVNode.realNode; // 如果topContainer是targetContainer,不需要在这里处理 - if (isSameContainer(topContainer, targetContainer)) { + if (topContainer === targetContainer) { return true; } } @@ -228,28 +213,28 @@ function isPortalRoot(vNode, targetContainer) { } // 获取根vNode节点 -export function getExactNode(targetVNode, targetContainer) { +export function findRoot(targetVNode, targetDom) { // 确认vNode节点是否准确,portal场景下可能祖先节点不准确 let vNode = targetVNode; while (vNode !== null) { if (vNode.tag === TreeRoot || vNode.tag === DomPortal) { - let container = vNode.realNode; - if (isSameContainer(container, targetContainer)) { + let dom = vNode.realNode; + if (dom === targetDom) { break; } - if (isPortalRoot(vNode, targetContainer)) { + if (isPortalRoot(vNode, targetDom)) { return null; } - while (container !== null) { - const parentNode = getNearestVNode(container); + while (dom !== null) { + const parentNode = getNearestVNode(dom); if (parentNode === null) { return null; } if (parentNode.tag === DomComponent || parentNode.tag === DomText) { - return getExactNode(parentNode, targetContainer); + return findRoot(parentNode, targetDom); } - container = container.parentNode; + dom = dom.parentNode; } } vNode = vNode.parent; diff --git a/scripts/__tests__/DomTest/Attribute.test.js b/scripts/__tests__/DomTest/Attribute.test.js index 49030e2f..32fe44a5 100755 --- a/scripts/__tests__/DomTest/Attribute.test.js +++ b/scripts/__tests__/DomTest/Attribute.test.js @@ -61,4 +61,10 @@ describe('Dom Attribute', () => { container.querySelector('div').setAttribute('data-first-name', 'Tom'); expect(container.querySelector('div').dataset.firstName).toBe('Tom'); }); -}); \ No newline at end of file + + it('style 自动加px', () => { + const div = Horizon.render(
, container); + expect(window.getComputedStyle(div).getPropertyValue('width')).toBe('10px'); + expect(window.getComputedStyle(div).getPropertyValue('height')).toBe('20px'); + }); +}); diff --git a/scripts/__tests__/DomTest/DomInput.test.js b/scripts/__tests__/DomTest/DomInput.test.js index d5649ff3..7d43b251 100755 --- a/scripts/__tests__/DomTest/DomInput.test.js +++ b/scripts/__tests__/DomTest/DomInput.test.js @@ -172,6 +172,11 @@ describe('Dom Input', () => { expect(realNode.getAttribute('value')).toBe('default'); }); + it('value为0、defaultValue为1,input 的value应该为0', () => { + const input = Horizon.render(, container); + expect(input.getAttribute('value')).toBe('0'); + }); + it('name属性', () => { let realNode = Horizon.render(, container); expect(realNode.name).toBe('name'); @@ -426,4 +431,4 @@ describe('Dom Input', () => { expect(container.querySelector('input').hasAttribute('value')).toBe(false); }); }); -}); \ No newline at end of file +});