Match-id-2909a47b27480d6ed5a321c4bab455c53313c6b9

This commit is contained in:
* 2022-01-26 10:28:41 +08:00 committed by *
commit e51f135a83
16 changed files with 145 additions and 145 deletions

View File

@ -24,11 +24,12 @@ const internalKeys = {
}; };
// 通过 VNode 实例获取 DOM 节点 // 通过 VNode 实例获取 DOM 节点
export function getDom(vNode: VNode): Element | Text | void { export function getDom(vNode: VNode): Element | Text | null {
const {tag} = vNode; const {tag} = vNode;
if (tag === DomComponent || tag === DomText) { if (tag === DomComponent || tag === DomText) {
return vNode.realNode; return vNode.realNode;
} }
return null;
} }
// 将 VNode 属性相关信息挂到 DOM 对象的特定属性上 // 将 VNode 属性相关信息挂到 DOM 对象的特定属性上

View File

@ -5,7 +5,7 @@ import {
import { import {
createDom, createDom,
} from './utils/DomCreator'; } from './utils/DomCreator';
import { getSelectionInfo, resetSelectionRange, selectionData } from './SelectionRangeHandler'; import { getSelectionInfo, resetSelectionRange, SelectionData } from './SelectionRangeHandler';
import { isElement, isComment, isDocument, isDocumentFragment, getDomTag, shouldAutoFocus } from './utils/Common'; import { isElement, isComment, isDocument, isDocumentFragment, getDomTag, shouldAutoFocus } from './utils/Common';
import { NSS } from './utils/DomCreator'; import { NSS } from './utils/DomCreator';
import { adjustStyleValue } from './DOMPropertiesHandler/StyleHandler'; import { adjustStyleValue } from './DOMPropertiesHandler/StyleHandler';
@ -37,7 +37,7 @@ export type Props = {
export type Container = (Element & { _treeRoot?: VNode }) | (Document & { _treeRoot?: VNode }); export type Container = (Element & { _treeRoot?: VNode }) | (Document & { _treeRoot?: VNode });
let selectionInfo: null | selectionData = null; let selectionInfo: null | SelectionData = null;
function getChildNS(parentNS: string | null, tagName: string): string { function getChildNS(parentNS: string | null, tagName: string): string {
if (parentNS === NSS.svg && tagName === 'foreignObject') { if (parentNS === NSS.svg && tagName === 'foreignObject') {
@ -54,12 +54,12 @@ function getChildNS(parentNS: string | null, tagName: string): string {
} }
// 获取容器 // 获取容器
export function getNSCtx(dom?: Container, parentNS: string, type: string): string { export function getNSCtx(parentNS: string, type: string, dom?: Container): string {
return dom ? getChildNS(dom.namespaceURI ?? null, dom.nodeName) : getChildNS(parentNS, type); return dom ? getChildNS(dom.namespaceURI ?? null, dom.nodeName) : getChildNS(parentNS, type);
} }
export function prepareForSubmit(): void { export function prepareForSubmit(): void {
selectionInfo = <selectionData>getSelectionInfo(); selectionInfo = <SelectionData>getSelectionInfo();
} }
export function resetAfterSubmit(): void { export function resetAfterSubmit(): void {

View File

@ -8,7 +8,7 @@ import {
} from '../../event/EventBinding'; } from '../../event/EventBinding';
import { isEventProp, isNativeElement } from '../validators/ValidateProps'; import { isEventProp, isNativeElement } from '../validators/ValidateProps';
function updateOneProp(dom, propName, propVal, isNativeTag, isInit?: boolean) { function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) {
if (propName === 'style') { if (propName === 'style') {
setStyles(dom, propVal); setStyles(dom, propVal);
} else if (propName === 'dangerouslySetInnerHTML') { } else if (propName === 'dangerouslySetInnerHTML') {
@ -42,7 +42,7 @@ export function setDomProps(
const propName = keysOfProps[i]; const propName = keysOfProps[i];
const propVal = props[propName]; const propVal = props[propName];
updateOneProp(dom, propName, propVal, isNativeTag, true); updateOneProp(dom, propName, isNativeTag, propVal, true);
} }
} }
@ -55,7 +55,7 @@ export function updateDomProps(
for (let i = 0; i < changeList.length; i++) { for (let i = 0; i < changeList.length; i++) {
const { propName, propVal } = changeList[i]; const { propName, propVal } = changeList[i];
updateOneProp(dom, propName, propVal, isNativeTag); updateOneProp(dom, propName, isNativeTag, propVal);
} }
} }
@ -111,7 +111,7 @@ export function compareProps(
for (let i = 0; i < keysOfNewProps.length; i++) { for (let i = 0; i < keysOfNewProps.length; i++) {
const propName = keysOfNewProps[i]; const propName = keysOfNewProps[i];
const newPropValue = newProps[propName]; const newPropValue = newProps[propName];
const oldPropValue = oldProps != null ? oldProps[propName] : undefined; const oldPropValue = oldProps != null ? oldProps[propName] : null;
if (newPropValue === oldPropValue || (newPropValue == null && oldPropValue == null)) { if (newPropValue === oldPropValue || (newPropValue == null && oldPropValue == null)) {
// 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理 // 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理

View File

@ -1,3 +1,20 @@
/**
* width: 10 => width: 10px
*
*
*/
export function adjustStyleValue(name, value) {
let validValue = value;
if (typeof value === 'number' && value !== 0 && isNeedUnitCSS(name)) {
validValue = `${value}px`;
} else if (value === '' || value == null || typeof value === 'boolean') {
validValue = '';
}
return validValue;
}
/** /**
* DOM style * DOM style
*/ */
@ -32,20 +49,3 @@ function isNeedUnitCSS(propName: string) {
|| propName.startsWith('box') || propName.startsWith('box')
|| propName.endsWith('Opacity')); || propName.endsWith('Opacity'));
} }
/**
* width: 10 => width: 10px
*
*
*/
export function adjustStyleValue(name, value) {
let validValue = value;
if (typeof value === 'number' && value !== 0 && isNeedUnitCSS(name)) {
validValue = `${value}px`;
} else if (value === '' || value == null || typeof value === 'boolean') {
validValue = '';
}
return validValue;
}

View File

@ -18,6 +18,13 @@ const svgHumpAttr = new Set(['allowReorder', 'autoReverse', 'baseFrequency', 'ba
'stitchTiles', 'surfaceScale','systemLanguage', 'tableValues', 'targetX', 'targetY', 'stitchTiles', 'surfaceScale','systemLanguage', 'tableValues', 'targetX', 'targetY',
'textLength','viewBox', 'viewTarget', 'xChannelSelector','yChannelSelector', 'zoomAndPan']); 'textLength','viewBox', 'viewTarget', 'xChannelSelector','yChannelSelector', 'zoomAndPan']);
// 驼峰 变 “-”
function convertToLowerCase(str) {
const replacer = (match, char) => `-${char.toLowerCase()}`;
return str.replace(/([A-Z])/g, replacer);
}
/** /**
* dom * dom
* attrName class * attrName class
@ -70,12 +77,3 @@ export function updateCommonProp(dom: Element, attrName: string, value: any, isN
} }
} }
} }
// 驼峰 变 “-”
function convertToLowerCase(str) {
const replacer = (match, char) => {
return `-${char.toLowerCase()}`;
}
return str.replace(/([A-Z])/g, replacer);
};

View File

@ -105,16 +105,16 @@ export function getSelectionInfo() {
}; };
} }
export interface selectionData { export interface SelectionData {
focusedDom: HTMLInputElement | HTMLTextAreaElement | void; focusedDom: HTMLInputElement | HTMLTextAreaElement | void;
selectionRange: { selectionRange: {
start: number; start: number | null;
end: number; end: number | null;
}; };
} }
// 防止选择范围内的信息因为节点删除或其他原因导致的信息丢失 // 防止选择范围内的信息因为节点删除或其他原因导致的信息丢失
export function resetSelectionRange(preSelectionRangeData: selectionData) { export function resetSelectionRange(preSelectionRangeData: SelectionData) {
// 当前 focus 的元素 // 当前 focus 的元素
const currentFocusedDom = getIFrameFocusedDom(); const currentFocusedDom = getIFrameFocusedDom();

View File

@ -6,7 +6,7 @@ export enum PROPERTY_TYPE {
STRING, // 普通的字符串类型 STRING, // 普通的字符串类型
SPECIAL, // 需要特殊处理的属性类型 SPECIAL, // 需要特殊处理的属性类型
BOOLEAN_STR, // 字符串类型的 true false BOOLEAN_STR, // 字符串类型的 true false
}; }
export type PropDetails = { export type PropDetails = {
propName: string; propName: string;
@ -15,10 +15,6 @@ export type PropDetails = {
attrNS: string | null; attrNS: string | null;
}; };
export function getPropDetails(name: string): PropDetails | null {
return propsDetailData[name] || null;
}
// 属性相关数据 // 属性相关数据
// 依次为 propertyName、type、attributeName、attributeNamespace不填则使用默认值 // 依次为 propertyName、type、attributeName、attributeNamespace不填则使用默认值
// type 默认 STRING // type 默认 STRING
@ -123,3 +119,7 @@ propertiesData.forEach(record => {
attrNS, attrNS,
}; };
}); });
export function getPropDetails(name: string): PropDetails | null {
return propsDetailData[name] || null;
}

View File

@ -34,6 +34,11 @@ function isInvalidBoolean(
return false; return false;
} }
// 是事件属性
export function isEventProp(propName) {
return propName.substr(0, 2) === 'on';
}
function isValidProp(tagName, name, value) { function isValidProp(tagName, name, value) {
// 校验事件名称 // 校验事件名称
if (isEventProp(name)) { if (isEventProp(name)) {
@ -79,11 +84,6 @@ export function isInvalidValue(
return false; return false;
} }
// 是事件属性
export function isEventProp(propName) {
return propName.substr(0, 2) === 'on';
}
// dev模式下校验属性是否合法 // dev模式下校验属性是否合法
export function validateProps(type, props) { export function validateProps(type, props) {
if (!props) { if (!props) {

View File

@ -1,14 +1,5 @@
import {HorizonSelect, IProperty} from '../utils/Interface'; import {HorizonSelect, IProperty} from '../utils/Interface';
// 更新 <option>
function updateValue(options, newValues: any, isMultiple: boolean) {
if (isMultiple) {
updateMultipleValue(options, newValues);
} else {
updateSingleValue(options, newValues);
}
}
function updateMultipleValue(options, newValues) { function updateMultipleValue(options, newValues) {
const newValueSet = new Set(); const newValueSet = new Set();
@ -39,6 +30,15 @@ function updateSingleValue(options, newValue) {
} }
} }
// 更新 <option>
function updateValue(options, newValues: any, isMultiple: boolean) {
if (isMultiple) {
updateMultipleValue(options, newValues);
} else {
updateSingleValue(options, newValues);
}
}
export function getSelectPropsWithoutValue(dom: HorizonSelect, properties: Object) { export function getSelectPropsWithoutValue(dom: HorizonSelect, properties: Object) {
return { return {
...properties, ...properties,

View File

@ -21,7 +21,6 @@ export type JSXElement = {
key: any; key: any;
ref: any; ref: any;
props: any; props: any;
belongClassVNode: any; belongClassVNode: any;
}; };

View File

@ -4,6 +4,7 @@
let isMessageLoopRunning = false; let isMessageLoopRunning = false;
let browserCallback = null; let browserCallback = null;
const { port1, port2 } = new MessageChannel();
export function isOverTime() { export function isOverTime() {
@ -33,7 +34,7 @@ const callRenderTasks = () => {
} }
}; };
const { port1, port2 } = new MessageChannel();
port1.onmessage = callRenderTasks; port1.onmessage = callRenderTasks;
export function requestBrowserCallback(callback) { export function requestBrowserCallback(callback) {

View File

@ -12,30 +12,6 @@ let callingQueueTask: any | null = null;
// 防止重入 // 防止重入
let isCallingRenderQueue = false; let isCallingRenderQueue = false;
export function pushRenderCallback(callback: RenderCallback) {
if (renderQueue === null) {
renderQueue = [callback];
// 高优先级的异步调度
callingQueueTask = runAsync(callRenderQueue, ImmediatePriority);
} else {
// 不需要调度在syncQueue创建的时候已经调度了
renderQueue.push(callback);
}
// 返回一个空对象用于区别null
return {};
}
export function callRenderQueueImmediate() {
if (callingQueueTask !== null) {
// 取消异步调度
cancelTask(callingQueueTask);
callingQueueTask = null;
}
callRenderQueue();
}
// 执行render回调 // 执行render回调
function callRenderQueue() { function callRenderQueue() {
if (!isCallingRenderQueue && renderQueue !== null) { if (!isCallingRenderQueue && renderQueue !== null) {
@ -64,3 +40,27 @@ function callRenderQueue() {
} }
} }
} }
export function pushRenderCallback(callback: RenderCallback) {
if (renderQueue === null) {
renderQueue = [callback];
// 高优先级的异步调度
callingQueueTask = runAsync(callRenderQueue, ImmediatePriority);
} else {
// 不需要调度在syncQueue创建的时候已经调度了
renderQueue.push(callback);
}
// 返回一个空对象用于区别null
return {};
}
export function callRenderQueueImmediate() {
if (callingQueueTask !== null) {
// 取消异步调度
cancelTask(callingQueueTask);
callingQueueTask = null;
}
callRenderQueue();
}

View File

@ -2,6 +2,7 @@
* *
*/ */
import { Node } from '../taskExecutor/TaskQueue';
import { import {
requestBrowserCallback, requestBrowserCallback,
isOverTime, isOverTime,
@ -21,39 +22,11 @@ let isProcessing = false;
// 调度中,等待浏览器回调 // 调度中,等待浏览器回调
let isWaiting = false; let isWaiting = false;
function runAsync(callback, priorityLevel= NormalPriority ) {
let increment;
switch (priorityLevel) {
case ImmediatePriority:
increment = -1;
break;
case NormalPriority:
default:
increment = 10000;
break;
}
const task = {
id: idCounter++,
callback,
order: idCounter + increment,
};
add(task);
if (!isWaiting && !isProcessing) {
isWaiting = true;
requestBrowserCallback(callTasks);
}
return task;
}
function callTasks() { function callTasks() {
isWaiting = false; isWaiting = false;
isProcessing = true; isProcessing = true;
let task = null; let task: Node | null= null;
try { try {
task = first(); task = first();
@ -89,6 +62,34 @@ function callTasks() {
} }
} }
function runAsync(callback, priorityLevel= NormalPriority ) {
let increment;
switch (priorityLevel) {
case ImmediatePriority:
increment = -1;
break;
case NormalPriority:
default:
increment = 10000;
break;
}
const task = {
id: idCounter++,
callback,
order: idCounter + increment,
};
add(task);
if (!isWaiting && !isProcessing) {
isWaiting = true;
requestBrowserCallback(callTasks);
}
return task;
}
function cancelTask(task) { function cancelTask(task) {
task.callback = null; task.callback = null;
} }

View File

@ -3,7 +3,7 @@
*/ */
type Queue = Array<Node>; type Queue = Array<Node>;
type Node = { export type Node = {
id: number; id: number;
order: number; order: number;
}; };
@ -11,15 +11,10 @@ type Node = {
// 任务队列 // 任务队列
const taskQueue: Queue = []; const taskQueue: Queue = [];
export function add(node: Node): void { function compare(a: Node, b: Node) {
// 查找第一个大于等于 value 的下标,都比 value 小则返回 -1 // 优先先用index排序其次用id
const idx = getBiggerIdx(node); const diff = a.order - b.order;
return diff !== 0 ? diff : a.id - b.id;
if (idx === -1) {
taskQueue.push(node);
} else {
taskQueue.splice(idx, 0, node);
}
} }
// 二分法查找第一个大于等于 value 的下标,都比 value 小则返回 -1时间复杂度O(logn) // 二分法查找第一个大于等于 value 的下标,都比 value 小则返回 -1时间复杂度O(logn)
@ -37,11 +32,22 @@ function getBiggerIdx(node: Node) {
} }
} }
return (left < taskQueue.length) ? left : -1; return left < taskQueue.length ? left : -1;
}
export function add(node: Node): void {
// 查找第一个大于等于 value 的下标,都比 value 小则返回 -1
const idx = getBiggerIdx(node);
if (idx === -1) {
taskQueue.push(node);
} else {
taskQueue.splice(idx, 0, node);
}
} }
export function first(): Node | null { export function first(): Node | null {
const val = taskQueue[0]; const val: Node | null | undefined = taskQueue[0];
return val !== undefined ? val : null; return val !== undefined ? val : null;
} }
@ -53,9 +59,3 @@ export function shift(): Node | null {
export function remove(node: Node) { export function remove(node: Node) {
taskQueue.splice(taskQueue.indexOf(node), 1); taskQueue.splice(taskQueue.indexOf(node), 1);
} }
function compare(a: Node, b: Node) {
// 优先先用index排序其次用id
const diff = a.order - b.order;
return diff !== 0 ? diff : a.id - b.id;
}

View File

@ -175,7 +175,7 @@ export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
// 此vNode无需更新但是子树需要 // 此vNode无需更新但是子树需要
if (!processing.isCreated && processing.child !== null) { if (!processing.isCreated && processing.child !== null) {
// 更新子节点 // 更新子节点
let child = processing.child; let child: VNode | null = processing.child;
while (child !== null) { while (child !== null) {
updateVNode(child, child.props); updateVNode(child, child.props);
updateVNodePath(child); updateVNodePath(child);

View File

@ -37,6 +37,19 @@ export function updateChildShouldUpdate(vNode: VNode) {
vNode.childShouldUpdate = false; vNode.childShouldUpdate = false;
} }
// 更新从当前节点到根节点的childShouldUpdate为true
export function setParentsChildShouldUpdate(parent: VNode | null) {
let node = parent;
while (node !== null) {
if (node.childShouldUpdate) {
break;
}
node.childShouldUpdate = true;
node = node.parent;
}
}
// 设置节点的所有父节点的childShouldUpdate // 设置节点的所有父节点的childShouldUpdate
export function updateParentsChildShouldUpdate(vNode: VNode) { export function updateParentsChildShouldUpdate(vNode: VNode) {
let node = vNode.parent; let node = vNode.parent;
@ -51,16 +64,3 @@ export function updateParentsChildShouldUpdate(vNode: VNode) {
} }
} }
} }
// 更新从当前节点到根节点的childShouldUpdate为true
export function setParentsChildShouldUpdate(parent: VNode | null) {
let node = parent;
while (node !== null) {
if (node.childShouldUpdate) {
break;
}
node.childShouldUpdate = true;
node = node.parent;
}
}