Match-id-70d03a8fc008ccce49a3f8517fc56c3d6ecbcf98
This commit is contained in:
commit
a1c73a6e2f
|
@ -19,7 +19,7 @@ import {
|
||||||
} from './valueHandler';
|
} from './valueHandler';
|
||||||
import {
|
import {
|
||||||
compareProps,
|
compareProps,
|
||||||
setDomProps, updateDomProps
|
setDomProps,
|
||||||
} from './DOMPropertiesHandler/DOMPropertiesHandler';
|
} from './DOMPropertiesHandler/DOMPropertiesHandler';
|
||||||
import { isNativeElement, validateProps } from './validators/ValidateProps';
|
import { isNativeElement, validateProps } from './validators/ValidateProps';
|
||||||
import { watchValueChange } from './valueHandler/ValueChangeHandler';
|
import { watchValueChange } from './valueHandler/ValueChangeHandler';
|
||||||
|
@ -91,7 +91,8 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo
|
||||||
const props: Object = getPropsWithoutValue(tagName, dom, rawProps);
|
const props: Object = getPropsWithoutValue(tagName, dom, rawProps);
|
||||||
|
|
||||||
// 初始化DOM属性(不包括value,defaultValue)
|
// 初始化DOM属性(不包括value,defaultValue)
|
||||||
setDomProps(tagName, dom, props);
|
const isNativeTag = isNativeElement(tagName, props);
|
||||||
|
setDomProps(dom, props, isNativeTag, true);
|
||||||
|
|
||||||
if (tagName === 'input' || tagName === 'textarea') {
|
if (tagName === 'input' || tagName === 'textarea') {
|
||||||
// 增加监听value和checked的set、get方法
|
// 增加监听value和checked的set、get方法
|
||||||
|
@ -110,7 +111,7 @@ export function getPropChangeList(
|
||||||
type: string,
|
type: string,
|
||||||
lastRawProps: Props,
|
lastRawProps: Props,
|
||||||
nextRawProps: Props,
|
nextRawProps: Props,
|
||||||
): Map<string, any> {
|
): Object {
|
||||||
// 校验两个对象的不同
|
// 校验两个对象的不同
|
||||||
validateProps(type, nextRawProps);
|
validateProps(type, nextRawProps);
|
||||||
|
|
||||||
|
@ -118,8 +119,7 @@ export function getPropChangeList(
|
||||||
const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps);
|
const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps);
|
||||||
const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps);
|
const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps);
|
||||||
|
|
||||||
const changeList = compareProps(oldProps, newProps);
|
return compareProps(oldProps, newProps);
|
||||||
return changeList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isTextChild(type: string, props: Props): boolean {
|
export function isTextChild(type: string, props: Props): boolean {
|
||||||
|
@ -168,7 +168,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
|
||||||
updateCommonProp(element, 'checked', newProps.checked, true);
|
updateCommonProp(element, 'checked', newProps.checked, true);
|
||||||
}
|
}
|
||||||
const isNativeTag = isNativeElement(type, newProps);
|
const isNativeTag = isNativeElement(type, newProps);
|
||||||
updateDomProps(element, changeList, isNativeTag);
|
setDomProps(element, changeList, isNativeTag, false);
|
||||||
updateValue(type, element, newProps);
|
updateValue(type, element, newProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,37 +6,15 @@ import { setStyles } from './StyleHandler';
|
||||||
import {
|
import {
|
||||||
listenNonDelegatedEvent
|
listenNonDelegatedEvent
|
||||||
} from '../../event/EventBinding';
|
} from '../../event/EventBinding';
|
||||||
import { isEventProp, isNativeElement } from '../validators/ValidateProps';
|
import { isEventProp } from '../validators/ValidateProps';
|
||||||
|
|
||||||
function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) {
|
// 初始化DOM属性和更新 DOM 属性
|
||||||
if (propName === 'style') {
|
|
||||||
setStyles(dom, propVal);
|
|
||||||
} else if (isEventProp(propName)) {
|
|
||||||
// 事件监听属性处理
|
|
||||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
|
||||||
listenNonDelegatedEvent(propName, dom, propVal);
|
|
||||||
}
|
|
||||||
} else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理
|
|
||||||
const type = typeof propVal;
|
|
||||||
if (type === 'string' || type === 'number') {
|
|
||||||
dom.textContent = propVal;
|
|
||||||
}
|
|
||||||
} else if (propName === 'dangerouslySetInnerHTML') {
|
|
||||||
dom.innerHTML = propVal.__html;
|
|
||||||
} else {
|
|
||||||
if (!isInit || (isInit && propVal != null)) {
|
|
||||||
updateCommonProp(dom, propName, propVal, isNativeTag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化DOM属性
|
|
||||||
export function setDomProps(
|
export function setDomProps(
|
||||||
tagName: string,
|
|
||||||
dom: Element,
|
dom: Element,
|
||||||
props: Object,
|
props: Object,
|
||||||
|
isNativeTag: boolean,
|
||||||
|
isInit: boolean,
|
||||||
): void {
|
): void {
|
||||||
const isNativeTag = isNativeElement(tagName, props);
|
|
||||||
const keysOfProps = Object.keys(props);
|
const keysOfProps = Object.keys(props);
|
||||||
let propName;
|
let propName;
|
||||||
let propVal;
|
let propVal;
|
||||||
|
@ -45,18 +23,23 @@ export function setDomProps(
|
||||||
propName = keysOfProps[i];
|
propName = keysOfProps[i];
|
||||||
propVal = props[propName];
|
propVal = props[propName];
|
||||||
|
|
||||||
updateOneProp(dom, propName, isNativeTag, propVal, true);
|
if (propName === 'style') {
|
||||||
}
|
setStyles(dom, propVal);
|
||||||
}
|
} else if (isEventProp(propName)) {
|
||||||
|
// 事件监听属性处理
|
||||||
// 更新 DOM 属性
|
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||||
export function updateDomProps(
|
listenNonDelegatedEvent(propName, dom, propVal);
|
||||||
dom: Element,
|
}
|
||||||
changeList: Map<string, any>,
|
} else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理
|
||||||
isNativeTag: boolean,
|
const type = typeof propVal;
|
||||||
): void {
|
if (type === 'string' || type === 'number') {
|
||||||
for(const [propName, propVal] of changeList) {
|
dom.textContent = propVal;
|
||||||
updateOneProp(dom, propName, isNativeTag, propVal);
|
}
|
||||||
|
} else if (propName === 'dangerouslySetInnerHTML') {
|
||||||
|
dom.innerHTML = propVal.__html;
|
||||||
|
} else if (!isInit || (isInit && propVal != null)) {
|
||||||
|
updateCommonProp(dom, propName, propVal, isNativeTag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +47,9 @@ export function updateDomProps(
|
||||||
export function compareProps(
|
export function compareProps(
|
||||||
oldProps: Object,
|
oldProps: Object,
|
||||||
newProps: Object,
|
newProps: Object,
|
||||||
): Map<string, any> {
|
): Object {
|
||||||
let updatesForStyle = {};
|
let updatesForStyle = {};
|
||||||
const toUpdateProps = new Map();
|
const toUpdateProps = {};
|
||||||
const keysOfOldProps = Object.keys(oldProps);
|
const keysOfOldProps = Object.keys(oldProps);
|
||||||
const keysOfNewProps = Object.keys(newProps);
|
const keysOfNewProps = Object.keys(newProps);
|
||||||
|
|
||||||
|
@ -98,11 +81,11 @@ export function compareProps(
|
||||||
continue;
|
continue;
|
||||||
} else if (isEventProp(propName)) {
|
} else if (isEventProp(propName)) {
|
||||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||||
toUpdateProps.set(propName, null);
|
toUpdateProps[propName] = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 其它属性都要加入到删除队列里面,等待删除
|
// 其它属性都要加入到删除队列里面,等待删除
|
||||||
toUpdateProps.set(propName, null);
|
toUpdateProps[propName] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +127,7 @@ export function compareProps(
|
||||||
}
|
}
|
||||||
} else { // 之前未设置 style 属性或者设置了空值
|
} else { // 之前未设置 style 属性或者设置了空值
|
||||||
if (Object.keys(updatesForStyle).length === 0) {
|
if (Object.keys(updatesForStyle).length === 0) {
|
||||||
toUpdateProps.set(propName, null);
|
toUpdateProps[propName] = null;
|
||||||
}
|
}
|
||||||
updatesForStyle = newPropValue;
|
updatesForStyle = newPropValue;
|
||||||
}
|
}
|
||||||
|
@ -153,25 +136,25 @@ export function compareProps(
|
||||||
oldHTML = oldPropValue ? oldPropValue.__html : undefined;
|
oldHTML = oldPropValue ? oldPropValue.__html : undefined;
|
||||||
if (newHTML != null) {
|
if (newHTML != null) {
|
||||||
if (oldHTML !== newHTML) {
|
if (oldHTML !== newHTML) {
|
||||||
toUpdateProps.set(propName, newPropValue);
|
toUpdateProps[propName] = newPropValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (propName === 'children') {
|
} else if (propName === 'children') {
|
||||||
if (typeof newPropValue === 'string' || typeof newPropValue === 'number') {
|
if (typeof newPropValue === 'string' || typeof newPropValue === 'number') {
|
||||||
toUpdateProps.set(propName, String(newPropValue));
|
toUpdateProps[propName] = String(newPropValue);
|
||||||
}
|
}
|
||||||
} else if (isEventProp(propName)) {
|
} else if (isEventProp(propName)) {
|
||||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||||
toUpdateProps.set(propName, newPropValue);
|
toUpdateProps[propName] = newPropValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toUpdateProps.set(propName, newPropValue);
|
toUpdateProps[propName] = newPropValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理style
|
// 处理style
|
||||||
if (Object.keys(updatesForStyle).length > 0) {
|
if (Object.keys(updatesForStyle).length > 0) {
|
||||||
toUpdateProps.set('style', updatesForStyle);
|
toUpdateProps['style'] = updatesForStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
return toUpdateProps;
|
return toUpdateProps;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler';
|
import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler';
|
||||||
import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler';
|
import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler';
|
||||||
import {
|
import {
|
||||||
addOnPrefix, setPropertyWritable,
|
setPropertyWritable,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { decorateNativeEvent } from './customEvents/EventFactory';
|
import { decorateNativeEvent } from './customEvents/EventFactory';
|
||||||
import { getListenersFromTree } from './ListenerGetter';
|
import { getListenersFromTree } from './ListenerGetter';
|
||||||
|
@ -27,7 +27,9 @@ function getCommonListeners(
|
||||||
target: null | EventTarget,
|
target: null | EventTarget,
|
||||||
isCapture: boolean,
|
isCapture: boolean,
|
||||||
): ListenerUnitList {
|
): ListenerUnitList {
|
||||||
const horizonEvtName = addOnPrefix(CommonEventToHorizonMap[nativeEvtName]);
|
const name = CommonEventToHorizonMap[nativeEvtName];
|
||||||
|
const horizonEvtName = !name ? '' : `on${name[0].toUpperCase()}${name.slice(1)}`; // 例:dragEnd -> onDragEnd
|
||||||
|
|
||||||
if (!horizonEvtName) {
|
if (!horizonEvtName) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,6 @@ export function isInputElement(dom?: HTMLElement): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 例:dragEnd -> onDragEnd
|
|
||||||
export function addOnPrefix(name) {
|
|
||||||
if (!name) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return 'on' + name[0].toUpperCase() + name.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setPropertyWritable(obj, propName) {
|
export function setPropertyWritable(obj, propName) {
|
||||||
const desc = Object.getOwnPropertyDescriptor(obj, propName);
|
const desc = Object.getOwnPropertyDescriptor(obj, propName);
|
||||||
if (!desc || !desc.writable) {
|
if (!desc || !desc.writable) {
|
||||||
|
|
|
@ -59,11 +59,11 @@ function collectDirtyNodes(vNode: VNode, parent: VNode): void {
|
||||||
const dirtyNodes = vNode.dirtyNodes;
|
const dirtyNodes = vNode.dirtyNodes;
|
||||||
if (dirtyNodes !== null && dirtyNodes.length) {
|
if (dirtyNodes !== null && dirtyNodes.length) {
|
||||||
if (parent.dirtyNodes === null) {
|
if (parent.dirtyNodes === null) {
|
||||||
parent.dirtyNodes = [...vNode.dirtyNodes];
|
parent.dirtyNodes = dirtyNodes;
|
||||||
} else {
|
} else {
|
||||||
parent.dirtyNodes.push(...vNode.dirtyNodes);
|
parent.dirtyNodes.push(...vNode.dirtyNodes);
|
||||||
|
dirtyNodes.length = 0;
|
||||||
}
|
}
|
||||||
dirtyNodes.length = 0;
|
|
||||||
vNode.dirtyNodes = null;
|
vNode.dirtyNodes = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ function buildVNodeTree(treeRoot: VNode) {
|
||||||
// 当在componentWillUnmount中调用setState,parent可能是null,因为startVNode会被clear
|
// 当在componentWillUnmount中调用setState,parent可能是null,因为startVNode会被clear
|
||||||
if (parent !== null) {
|
if (parent !== null) {
|
||||||
resetNamespaceCtx(parent);
|
resetNamespaceCtx(parent);
|
||||||
setNamespaceCtx(parent, parent.outerDom);
|
setNamespaceCtx(parent, parent.realNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 恢复父节点的context
|
// 恢复父节点的context
|
||||||
|
|
|
@ -39,7 +39,7 @@ export type ContextType<T> = {
|
||||||
export type PortalType = {
|
export type PortalType = {
|
||||||
vtype: number;
|
vtype: number;
|
||||||
key: null | string;
|
key: null | string;
|
||||||
outerDom: any;
|
realNode: any;
|
||||||
children: any;
|
children: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,6 @@ export enum UpdateState {
|
||||||
Error = 'Error',
|
Error = 'Error',
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化更新数组
|
|
||||||
export function createUpdateArray(vNode: VNode): void {
|
|
||||||
vNode.updates = []; // 新产生的update会加入这个数组
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建update对象
|
// 创建update对象
|
||||||
export function newUpdate(): Update {
|
export function newUpdate(): Update {
|
||||||
return {
|
return {
|
||||||
|
@ -35,8 +30,11 @@ export function newUpdate(): Update {
|
||||||
// 将update对象加入updates
|
// 将update对象加入updates
|
||||||
export function pushUpdate(vNode: VNode, update: Update) {
|
export function pushUpdate(vNode: VNode, update: Update) {
|
||||||
const updates = vNode.updates;
|
const updates = vNode.updates;
|
||||||
|
if (updates !== null) {
|
||||||
updates?.push(update);
|
updates.push(update);
|
||||||
|
} else {
|
||||||
|
vNode.updates = [update];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据update获取新的state
|
// 根据update获取新的state
|
||||||
|
@ -98,12 +96,14 @@ export function processUpdates(vNode: VNode, inst: any, props: any): void {
|
||||||
const updates: Updates = vNode.updates;
|
const updates: Updates = vNode.updates;
|
||||||
vNode.isForceUpdate = false;
|
vNode.isForceUpdate = false;
|
||||||
|
|
||||||
const toProcessUpdates = [...updates];
|
if (updates !== null) {
|
||||||
updates.length = 0;
|
const toProcessUpdates = [...updates];
|
||||||
|
updates.length = 0;
|
||||||
if (toProcessUpdates.length) {
|
if (toProcessUpdates.length) {
|
||||||
calcUpdates(vNode, props, inst, toProcessUpdates);
|
calcUpdates(vNode, props, inst, toProcessUpdates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pushForceUpdate(vNode: VNode) {
|
export function pushForceUpdate(vNode: VNode) {
|
||||||
|
|
|
@ -3,13 +3,13 @@ import type {PortalType} from '../Types';
|
||||||
|
|
||||||
export function createPortal(
|
export function createPortal(
|
||||||
children: any,
|
children: any,
|
||||||
outerDom: any,
|
realNode: any,
|
||||||
key: string = '',
|
key: string = '',
|
||||||
): PortalType {
|
): PortalType {
|
||||||
return {
|
return {
|
||||||
vtype: TYPE_PORTAL,
|
vtype: TYPE_PORTAL,
|
||||||
key: key == '' ? '' : '' + key,
|
key: key == '' ? '' : '' + key,
|
||||||
children,
|
children,
|
||||||
outerDom,
|
realNode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (newChild.vtype === TYPE_PORTAL) {
|
} else if (newChild.vtype === TYPE_PORTAL) {
|
||||||
if (oldNode === null || oldNode.tag !== DomPortal || oldNode.outerDom !== newChild.outerDom) {
|
if (oldNode === null || oldNode.tag !== DomPortal || oldNode.realNode !== newChild.realNode) {
|
||||||
resultNode = createPortalVNode(newChild);
|
resultNode = createPortalVNode(newChild);
|
||||||
} else {
|
} else {
|
||||||
resultNode = updateVNode(oldNode, newChild.children || []);
|
resultNode = updateVNode(oldNode, newChild.children || []);
|
||||||
|
@ -578,7 +578,7 @@ function diffObjectNodeHandler(
|
||||||
} else if (newChild.vtype === TYPE_PORTAL) {
|
} else if (newChild.vtype === TYPE_PORTAL) {
|
||||||
if (canReuseNode) {
|
if (canReuseNode) {
|
||||||
// 可以复用
|
// 可以复用
|
||||||
if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) {
|
if (canReuseNode.tag === DomPortal && canReuseNode.realNode === newChild.realNode) {
|
||||||
resultNode = updateVNode(canReuseNode, newChild.children || []);
|
resultNode = updateVNode(canReuseNode, newChild.children || []);
|
||||||
startDelVNode = canReuseNode.next;
|
startDelVNode = canReuseNode.next;
|
||||||
resultNode.next = null;
|
resultNode.next = null;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import componentRenders from './index';
|
||||||
function handlerContext(processing: VNode) {
|
function handlerContext(processing: VNode) {
|
||||||
switch (processing.tag) {
|
switch (processing.tag) {
|
||||||
case TreeRoot:
|
case TreeRoot:
|
||||||
setNamespaceCtx(processing, processing.outerDom);
|
setNamespaceCtx(processing, processing.realNode);
|
||||||
break;
|
break;
|
||||||
case DomComponent:
|
case DomComponent:
|
||||||
setNamespaceCtx(processing);
|
setNamespaceCtx(processing);
|
||||||
|
@ -29,7 +29,7 @@ function handlerContext(processing: VNode) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DomPortal:
|
case DomPortal:
|
||||||
setNamespaceCtx(processing, processing.outerDom);
|
setNamespaceCtx(processing, processing.realNode);
|
||||||
break;
|
break;
|
||||||
case ContextProvider: {
|
case ContextProvider: {
|
||||||
const newValue = processing.props.value;
|
const newValue = processing.props.value;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import {
|
||||||
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
|
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
|
||||||
import { markRef } from './BaseComponent';
|
import { markRef } from './BaseComponent';
|
||||||
import {
|
import {
|
||||||
createUpdateArray,
|
|
||||||
processUpdates,
|
processUpdates,
|
||||||
} from '../UpdateHandler';
|
} from '../UpdateHandler';
|
||||||
import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver';
|
import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver';
|
||||||
|
@ -47,15 +46,13 @@ function mountInstance(clazz, processing: VNode, nextProps: object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造实例
|
// 构造实例
|
||||||
callConstructor(processing, clazz, nextProps);
|
const inst = callConstructor(processing, clazz, nextProps);
|
||||||
|
|
||||||
const inst = processing.realNode;
|
|
||||||
inst.props = nextProps;
|
inst.props = nextProps;
|
||||||
inst.state = processing.state;
|
inst.state = processing.state;
|
||||||
inst.context = getCurrentContext(clazz, processing);
|
inst.context = getCurrentContext(clazz, processing);
|
||||||
inst.refs = {};
|
inst.refs = {};
|
||||||
|
|
||||||
createUpdateArray(processing);
|
|
||||||
processUpdates(processing, inst, nextProps);
|
processUpdates(processing, inst, nextProps);
|
||||||
inst.state = processing.state;
|
inst.state = processing.state;
|
||||||
|
|
||||||
|
@ -106,7 +103,15 @@ function markLifeCycle(processing: VNode, nextProps: object, shouldUpdate: Boole
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于类组件
|
// 用于类组件
|
||||||
export function captureClassComponent(processing: VNode, clazz: any, nextProps: object): VNode | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
|
let clazz = processing.type;
|
||||||
|
let nextProps = processing.props;
|
||||||
|
if (processing.isLazyComponent) {
|
||||||
|
nextProps = mergeDefaultProps(clazz, nextProps);
|
||||||
|
if (processing.promiseResolve) { // 该函数被 lazy 组件使用,未加载的组件需要加载组件的真实内容
|
||||||
|
clazz = clazz._load(clazz._content);
|
||||||
|
}
|
||||||
|
}
|
||||||
const isOldCxtExist = isOldProvider(clazz);
|
const isOldCxtExist = isOldProvider(clazz);
|
||||||
cacheOldCtx(processing, isOldCxtExist);
|
cacheOldCtx(processing, isOldCxtExist);
|
||||||
|
|
||||||
|
@ -123,18 +128,13 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
|
||||||
const newContext = getCurrentContext(clazz, processing);
|
const newContext = getCurrentContext(clazz, processing);
|
||||||
|
|
||||||
// 子节点抛出异常时,如果本class是个捕获异常的处理节点,这时候oldProps是null,所以需要使用props
|
// 子节点抛出异常时,如果本class是个捕获异常的处理节点,这时候oldProps是null,所以需要使用props
|
||||||
let oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
|
const oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
|
||||||
if (processing.isLazyComponent) {
|
|
||||||
oldProps = mergeDefaultProps(processing.type, oldProps);
|
|
||||||
}
|
|
||||||
inst.props = oldProps;
|
|
||||||
|
|
||||||
if (oldProps !== processing.props || inst.context !== newContext) {
|
if (oldProps !== processing.props || inst.context !== newContext) {
|
||||||
// 在已挂载的组件接收新的 props 之前被调用
|
// 在已挂载的组件接收新的 props 之前被调用
|
||||||
callComponentWillReceiveProps(inst, nextProps, newContext);
|
callComponentWillReceiveProps(inst, nextProps, newContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.state = processing.state;
|
|
||||||
processUpdates(processing, inst, nextProps);
|
processUpdates(processing, inst, nextProps);
|
||||||
|
|
||||||
// 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新
|
// 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新
|
||||||
|
@ -183,13 +183,6 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function captureRender(processing: VNode): VNode | null {
|
|
||||||
const clazz = processing.type;
|
|
||||||
const props = processing.props;
|
|
||||||
const nextProps = processing.isLazyComponent ? mergeDefaultProps(clazz, props) : props;
|
|
||||||
return captureClassComponent(processing, clazz, nextProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bubbleRender(processing: VNode) {
|
export function bubbleRender(processing: VNode) {
|
||||||
if (isOldProvider(processing.type)) {
|
if (isOldProvider(processing.type)) {
|
||||||
resetOldCtx(processing);
|
resetOldCtx(processing);
|
||||||
|
|
|
@ -38,14 +38,15 @@ function updateDom(
|
||||||
oldProps,
|
oldProps,
|
||||||
newProps,
|
newProps,
|
||||||
);
|
);
|
||||||
processing.changeList = changeList;
|
|
||||||
|
|
||||||
// 输入类型的直接标记更新
|
// 输入类型的直接标记更新
|
||||||
if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') {
|
if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') {
|
||||||
FlagUtils.markUpdate(processing);
|
FlagUtils.markUpdate(processing);
|
||||||
|
processing.changeList = changeList;
|
||||||
} else {
|
} else {
|
||||||
// 其它的类型,数据有变化才标记更新
|
// 其它的类型,数据有变化才标记更新
|
||||||
if (changeList.size) {
|
if (Object.keys(changeList).length) {
|
||||||
|
processing.changeList = changeList;
|
||||||
FlagUtils.markUpdate(processing);
|
FlagUtils.markUpdate(processing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +106,7 @@ export function bubbleRender(processing: VNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function captureDomComponent(processing: VNode): VNode | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
setNamespaceCtx(processing);
|
setNamespaceCtx(processing);
|
||||||
|
|
||||||
const type = processing.type;
|
const type = processing.type;
|
||||||
|
@ -127,7 +128,3 @@ function captureDomComponent(processing: VNode): VNode | null {
|
||||||
processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated);
|
processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated);
|
||||||
return processing.child;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function captureRender(processing: VNode): VNode | null {
|
|
||||||
return captureDomComponent(processing);
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ export function bubbleRender(processing: VNode) {
|
||||||
resetNamespaceCtx(processing);
|
resetNamespaceCtx(processing);
|
||||||
|
|
||||||
if (processing.isCreated) {
|
if (processing.isCreated) {
|
||||||
prePortal(processing.outerDom);
|
prePortal(processing.realNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function capturePortalComponent(processing: VNode) {
|
function capturePortalComponent(processing: VNode) {
|
||||||
setNamespaceCtx(processing, processing.outerDom);
|
setNamespaceCtx(processing, processing.realNode);
|
||||||
|
|
||||||
const newElements = processing.props;
|
const newElements = processing.props;
|
||||||
if (processing.isCreated) {
|
if (processing.isCreated) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from '../vnode/VNodeTags';
|
} from '../vnode/VNodeTags';
|
||||||
import { throwIfTrue } from '../utils/throwIfTrue';
|
import { throwIfTrue } from '../utils/throwIfTrue';
|
||||||
import { captureFunctionComponent } from './FunctionComponent';
|
import { captureFunctionComponent } from './FunctionComponent';
|
||||||
import { captureClassComponent } from './ClassComponent';
|
import { captureRender as captureClassComponent } from './ClassComponent';
|
||||||
import { captureMemoComponent } from './MemoComponent';
|
import { captureMemoComponent } from './MemoComponent';
|
||||||
|
|
||||||
export function bubbleRender() { }
|
export function bubbleRender() { }
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function bubbleRender(processing: VNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTreeRoot(processing) {
|
function updateTreeRoot(processing) {
|
||||||
setNamespaceCtx(processing, processing.outerDom);
|
setNamespaceCtx(processing, processing.realNode);
|
||||||
|
|
||||||
const updates = processing.updates;
|
const updates = processing.updates;
|
||||||
throwIfTrue(
|
throwIfTrue(
|
||||||
|
|
|
@ -118,15 +118,19 @@ export function callComponentWillUpdate(inst, newProps, newState, nextContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) {
|
export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) {
|
||||||
const oldState = inst.state;
|
|
||||||
if (inst.componentWillReceiveProps) {
|
if (inst.componentWillReceiveProps) {
|
||||||
|
const oldState = inst.state;
|
||||||
inst.componentWillReceiveProps(newProps, newContext);
|
inst.componentWillReceiveProps(newProps, newContext);
|
||||||
|
if (inst.state !== oldState) {
|
||||||
|
changeStateContent.call(inst, UpdateState.Override, inst.state, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (inst.UNSAFE_componentWillReceiveProps) {
|
if (inst.UNSAFE_componentWillReceiveProps) {
|
||||||
|
const oldState = inst.state;
|
||||||
inst.UNSAFE_componentWillReceiveProps(newProps, newContext);
|
inst.UNSAFE_componentWillReceiveProps(newProps, newContext);
|
||||||
}
|
if (inst.state !== oldState) {
|
||||||
if (inst.state !== oldState) {
|
changeStateContent.call(inst, UpdateState.Override, inst.state, null);
|
||||||
changeStateContent.call(inst, UpdateState.Override, inst.state, null);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,12 +225,9 @@ function submitAddition(vNode: VNode): void {
|
||||||
let tag;
|
let tag;
|
||||||
while (parent !== null) {
|
while (parent !== null) {
|
||||||
tag = parent.tag;
|
tag = parent.tag;
|
||||||
if (tag === DomComponent) {
|
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||||
parentDom = parent.realNode;
|
parentDom = parent.realNode;
|
||||||
break;
|
break;
|
||||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
|
||||||
parentDom = parent.outerDom;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
@ -292,12 +289,9 @@ function unmountDomComponents(vNode: VNode): void {
|
||||||
let tag;
|
let tag;
|
||||||
while (parent !== null) {
|
while (parent !== null) {
|
||||||
tag = parent.tag;
|
tag = parent.tag;
|
||||||
if (tag === DomComponent) {
|
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||||
currentParent = parent.realNode;
|
currentParent = parent.realNode;
|
||||||
break;
|
break;
|
||||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
|
||||||
currentParent = parent.outerDom;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +306,7 @@ function unmountDomComponents(vNode: VNode): void {
|
||||||
removeChildDom(currentParent, node.realNode);
|
removeChildDom(currentParent, node.realNode);
|
||||||
} else if (node.tag === DomPortal) {
|
} else if (node.tag === DomPortal) {
|
||||||
if (node.child !== null) {
|
if (node.child !== null) {
|
||||||
currentParent = node.outerDom;
|
currentParent = node.realNode;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unmountVNode(node);
|
unmountVNode(node);
|
||||||
|
@ -349,12 +343,9 @@ function submitClear(vNode: VNode): void {
|
||||||
let tag;
|
let tag;
|
||||||
while (parent !== null) {
|
while (parent !== null) {
|
||||||
tag = parent.tag;
|
tag = parent.tag;
|
||||||
if (tag === DomComponent) {
|
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||||
parentDom = parent.realNode;
|
parentDom = parent.realNode;
|
||||||
break;
|
break;
|
||||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
|
||||||
parentDom = parent.outerDom;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ export class VNode {
|
||||||
dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组
|
dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组
|
||||||
shouldUpdate: boolean = false;
|
shouldUpdate: boolean = false;
|
||||||
childShouldUpdate: boolean = false;
|
childShouldUpdate: boolean = false;
|
||||||
outerDom: any;
|
|
||||||
task: any;
|
task: any;
|
||||||
|
|
||||||
// 使用这个变量来记录修改前的值,用于恢复。
|
// 使用这个变量来记录修改前的值,用于恢复。
|
||||||
|
@ -67,7 +66,7 @@ export class VNode {
|
||||||
|
|
||||||
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
||||||
|
|
||||||
constructor(tag: VNodeTag, props: any, key: null | string, outerDom) {
|
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
||||||
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
||||||
|
@ -75,10 +74,9 @@ export class VNode {
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case TreeRoot:
|
case TreeRoot:
|
||||||
this.outerDom = outerDom;
|
this.realNode = realNode;
|
||||||
this.task = null;
|
this.task = null;
|
||||||
this.toUpdateNodes = new Set<VNode>();
|
this.toUpdateNodes = new Set<VNode>();
|
||||||
this.realNode = null;
|
|
||||||
this.updates = null;
|
this.updates = null;
|
||||||
this.stateCallbacks = null;
|
this.stateCallbacks = null;
|
||||||
this.state = null;
|
this.state = null;
|
||||||
|
@ -138,6 +136,7 @@ export class VNode {
|
||||||
this.stateCallbacks = null;
|
this.stateCallbacks = null;
|
||||||
this.isLazyComponent = true;
|
this.isLazyComponent = true;
|
||||||
this.lazyType = null;
|
this.lazyType = null;
|
||||||
|
this.updates = null;
|
||||||
break;
|
break;
|
||||||
case Fragment:
|
case Fragment:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
MemoComponent,
|
MemoComponent,
|
||||||
SuspenseComponent,
|
SuspenseComponent,
|
||||||
} from './VNodeTags';
|
} from './VNodeTags';
|
||||||
import { createUpdateArray } from '../UpdateHandler';
|
|
||||||
import {
|
import {
|
||||||
TYPE_CONTEXT,
|
TYPE_CONTEXT,
|
||||||
TYPE_FORWARD_REF, TYPE_FRAGMENT,
|
TYPE_FORWARD_REF, TYPE_FRAGMENT,
|
||||||
|
@ -39,8 +38,8 @@ const typeMap = {
|
||||||
[TYPE_LAZY]: LazyComponent,
|
[TYPE_LAZY]: LazyComponent,
|
||||||
};
|
};
|
||||||
|
|
||||||
const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, outerDom?: any): VNode {
|
const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, realNode?: any): VNode {
|
||||||
return new VNode(tag, vNodeProps, key, outerDom);
|
return new VNode(tag, vNodeProps, key, realNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
function isClassComponent(comp: Function) {
|
function isClassComponent(comp: Function) {
|
||||||
|
@ -100,7 +99,7 @@ export function createPortalVNode(portal) {
|
||||||
const children = portal.children ?? [];
|
const children = portal.children ?? [];
|
||||||
const vNode = newVirtualNode(DomPortal, portal.key, children);
|
const vNode = newVirtualNode(DomPortal, portal.key, children);
|
||||||
vNode.shouldUpdate = true;
|
vNode.shouldUpdate = true;
|
||||||
vNode.outerDom = portal.outerDom;
|
vNode.realNode = portal.realNode;
|
||||||
return vNode;
|
return vNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +136,7 @@ export function createUndeterminedVNode(type, key, props) {
|
||||||
export function createTreeRootVNode(container) {
|
export function createTreeRootVNode(container) {
|
||||||
const vNode = newVirtualNode(TreeRoot, null, null, container);
|
const vNode = newVirtualNode(TreeRoot, null, null, container);
|
||||||
vNode.path += 0;
|
vNode.path += 0;
|
||||||
createUpdateArray(vNode);
|
vNode.updates = [];
|
||||||
return vNode;
|
return vNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +149,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
|
||||||
vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]);
|
vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]);
|
||||||
vNode.path += 0;
|
vNode.path += 0;
|
||||||
|
|
||||||
createUpdateArray(vNode);
|
vNode.updates = [];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,10 @@ const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
|
||||||
|
|
||||||
export class FlagUtils {
|
export class FlagUtils {
|
||||||
static removeFlag(node: VNode, flag: number) {
|
static removeFlag(node: VNode, flag: number) {
|
||||||
const flags = node.flags;
|
node.flags &= ~flag;
|
||||||
node.flags = flags & (~flag);
|
|
||||||
}
|
}
|
||||||
static removeLifecycleEffectFlags(node) {
|
static removeLifecycleEffectFlags(node) {
|
||||||
const flags = node.flags;
|
node.flags &= ~LifecycleEffectArr;
|
||||||
node.flags = flags & (~LifecycleEffectArr);
|
|
||||||
}
|
}
|
||||||
static hasAnyFlag(node: VNode) { // 有标志位
|
static hasAnyFlag(node: VNode) { // 有标志位
|
||||||
return node.flags !== InitFlag;
|
return node.flags !== InitFlag;
|
||||||
|
|
|
@ -210,7 +210,7 @@ function isPortalRoot(vNode, targetContainer) {
|
||||||
while (topVNode !== null) {
|
while (topVNode !== null) {
|
||||||
const grandTag = topVNode.tag;
|
const grandTag = topVNode.tag;
|
||||||
if (grandTag === TreeRoot || grandTag === DomPortal) {
|
if (grandTag === TreeRoot || grandTag === DomPortal) {
|
||||||
const topContainer = topVNode.outerDom;
|
const topContainer = topVNode.realNode;
|
||||||
// 如果topContainer是targetContainer,不需要在这里处理
|
// 如果topContainer是targetContainer,不需要在这里处理
|
||||||
if (isSameContainer(topContainer, targetContainer)) {
|
if (isSameContainer(topContainer, targetContainer)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -229,7 +229,7 @@ export function getExactNode(targetVNode, targetContainer) {
|
||||||
let vNode = targetVNode;
|
let vNode = targetVNode;
|
||||||
while (vNode !== null) {
|
while (vNode !== null) {
|
||||||
if (vNode.tag === TreeRoot || vNode.tag === DomPortal) {
|
if (vNode.tag === TreeRoot || vNode.tag === DomPortal) {
|
||||||
let container = vNode.outerDom;
|
let container = vNode.realNode;
|
||||||
if (isSameContainer(container, targetContainer)) {
|
if (isSameContainer(container, targetContainer)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue