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 节点
export function getDom(vNode: VNode): Element | Text | void {
export function getDom(vNode: VNode): Element | Text | null {
const {tag} = vNode;
if (tag === DomComponent || tag === DomText) {
return vNode.realNode;
}
return null;
}
// 将 VNode 属性相关信息挂到 DOM 对象的特定属性上

View File

@ -5,7 +5,7 @@ import {
import {
createDom,
} 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 { NSS } from './utils/DomCreator';
import { adjustStyleValue } from './DOMPropertiesHandler/StyleHandler';
@ -37,7 +37,7 @@ export type Props = {
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 {
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);
}
export function prepareForSubmit(): void {
selectionInfo = <selectionData>getSelectionInfo();
selectionInfo = <SelectionData>getSelectionInfo();
}
export function resetAfterSubmit(): void {

View File

@ -8,7 +8,7 @@ import {
} from '../../event/EventBinding';
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') {
setStyles(dom, propVal);
} else if (propName === 'dangerouslySetInnerHTML') {
@ -42,7 +42,7 @@ export function setDomProps(
const propName = keysOfProps[i];
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++) {
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++) {
const propName = keysOfNewProps[i];
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)) {
// 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理

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
*/
@ -32,20 +49,3 @@ function isNeedUnitCSS(propName: string) {
|| propName.startsWith('box')
|| 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',
'textLength','viewBox', 'viewTarget', 'xChannelSelector','yChannelSelector', 'zoomAndPan']);
// 驼峰 变 “-”
function convertToLowerCase(str) {
const replacer = (match, char) => `-${char.toLowerCase()}`;
return str.replace(/([A-Z])/g, replacer);
}
/**
* dom
* 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;
selectionRange: {
start: number;
end: number;
start: number | null;
end: number | null;
};
}
// 防止选择范围内的信息因为节点删除或其他原因导致的信息丢失
export function resetSelectionRange(preSelectionRangeData: selectionData) {
export function resetSelectionRange(preSelectionRangeData: SelectionData) {
// 当前 focus 的元素
const currentFocusedDom = getIFrameFocusedDom();

View File

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

View File

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

View File

@ -1,14 +1,5 @@
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) {
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) {
return {
...properties,

View File

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

View File

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

View File

@ -12,30 +12,6 @@ let callingQueueTask: any | null = null;
// 防止重入
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回调
function callRenderQueue() {
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 {
requestBrowserCallback,
isOverTime,
@ -21,39 +22,11 @@ let isProcessing = 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() {
isWaiting = false;
isProcessing = true;
let task = null;
let task: Node | null= null;
try {
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) {
task.callback = null;
}

View File

@ -3,7 +3,7 @@
*/
type Queue = Array<Node>;
type Node = {
export type Node = {
id: number;
order: number;
};
@ -11,15 +11,10 @@ type Node = {
// 任务队列
const taskQueue: Queue = [];
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);
}
function compare(a: Node, b: Node) {
// 优先先用index排序其次用id
const diff = a.order - b.order;
return diff !== 0 ? diff : a.id - b.id;
}
// 二分法查找第一个大于等于 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 {
const val = taskQueue[0];
const val: Node | null | undefined = taskQueue[0];
return val !== undefined ? val : null;
}
@ -53,9 +59,3 @@ export function shift(): Node | null {
export function remove(node: Node) {
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无需更新但是子树需要
if (!processing.isCreated && processing.child !== null) {
// 更新子节点
let child = processing.child;
let child: VNode | null = processing.child;
while (child !== null) {
updateVNode(child, child.props);
updateVNodePath(child);

View File

@ -37,6 +37,19 @@ export function updateChildShouldUpdate(vNode: VNode) {
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
export function updateParentsChildShouldUpdate(vNode: VNode) {
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;
}
}