Match-id-846c52a6c0ddfcb4167efc73e2ef3aa481e59275

This commit is contained in:
* 2023-04-18 10:57:02 +08:00
commit e63af180be
14 changed files with 251 additions and 249 deletions

View File

@ -37,35 +37,6 @@ export function shouldControlValue(): boolean {
return changeEventTargets !== null && changeEventTargets.length > 0;
}
// 从缓存队列中对受控组件进行赋值
export function tryControlValue() {
if (!changeEventTargets) {
return;
}
changeEventTargets.forEach(target => {
controlValue(target);
});
changeEventTargets = null;
}
// 受控组件值重新赋值
function controlValue(target: Element) {
const props = getVNodeProps(target);
if (props) {
const type = getDomTag(target);
switch (type) {
case 'input':
controlInputValue(<HTMLInputElement>target, props);
break;
case 'textarea':
updateTextareaValue(<HTMLTextAreaElement>target, props);
break;
default:
break;
}
}
}
function controlInputValue(inputDom: HTMLInputElement, props: Props) {
const { name, type } = props;
@ -87,3 +58,32 @@ function controlInputValue(inputDom: HTMLInputElement, props: Props) {
updateInputValue(inputDom, props);
}
}
// 受控组件值重新赋值
function controlValue(target: Element) {
const props = getVNodeProps(target);
if (props) {
const type = getDomTag(target);
switch (type) {
case 'input':
controlInputValue(<HTMLInputElement>target, props);
break;
case 'textarea':
updateTextareaValue(<HTMLTextAreaElement>target, props);
break;
default:
break;
}
}
}
// 从缓存队列中对受控组件进行赋值
export function tryControlValue() {
if (!changeEventTargets) {
return;
}
changeEventTargets.forEach(target => {
controlValue(target);
});
changeEventTargets = null;
}

View File

@ -54,15 +54,12 @@ export type ReduxMiddleware = (
type Reducer = (state: any, action: ReduxAction) => any;
function mergeData(state, data) {
console.log('merging data', { state, data });
if (!data) {
console.log('!data');
state.stateWrapper = data;
return;
}
if (Array.isArray(data) && Array.isArray(state?.stateWrapper)) {
console.log('data is array');
state.stateWrapper.length = data.length;
data.forEach((item, idx) => {
if (item != state.stateWrapper[idx]) {
@ -73,9 +70,10 @@ function mergeData(state, data) {
}
if (typeof data === 'object' && typeof state?.stateWrapper === 'object') {
console.log('data is object');
Object.keys(state.stateWrapper).forEach(key => {
if (!data.hasOwnProperty(key)) delete state.stateWrapper[key];
if (!Object.prototype.hasOwnProperty.call(data, key)) {
delete state.stateWrapper[key];
}
});
Object.entries(data).forEach(([key, value]) => {
@ -86,7 +84,6 @@ function mergeData(state, data) {
return;
}
console.log('data is primitive or type mismatch');
state.stateWrapper = data;
}
@ -106,7 +103,6 @@ export function createStore(reducer: Reducer, preloadedState?: any, enhancers?):
if (result === undefined) {
return;
} // NOTE: reducer should never return undefined, in this case, do not change state
// mergeData(state,result);
state.stateWrapper = result;
},
},
@ -115,10 +111,6 @@ export function createStore(reducer: Reducer, preloadedState?: any, enhancers?):
},
})();
// store.$subscribe(()=>{
// console.log('changed');
// });
const result = {
reducer,
getState: function () {
@ -157,12 +149,6 @@ export function combineReducers(reducers: { [key: string]: Reducer }): Reducer {
};
}
export function applyMiddleware(...middlewares: ReduxMiddleware[]): (store: ReduxStoreHandler) => void {
return store => {
return applyMiddlewares(store, middlewares);
};
}
function applyMiddlewares(store: ReduxStoreHandler, middlewares: ReduxMiddleware[]): void {
middlewares = middlewares.slice();
middlewares.reverse();
@ -173,6 +159,12 @@ function applyMiddlewares(store: ReduxStoreHandler, middlewares: ReduxMiddleware
store.dispatch = dispatch;
}
export function applyMiddleware(...middlewares: ReduxMiddleware[]): (store: ReduxStoreHandler) => void {
return store => {
return applyMiddlewares(store, middlewares);
};
}
type ActionCreator = (...params: any[]) => ReduxAction;
type ActionCreators = { [key: string]: ActionCreator };
export type BoundActionCreator = (...params: any[]) => void;

View File

@ -18,6 +18,12 @@ import type { VNode } from '../Types';
import { getLastTimeHook, setLastTimeHook, setCurrentHook, getNextHook } from './BaseHook';
import { HookStage, setHookStage } from './HookStage';
function resetGlobalVariable() {
setHookStage(null);
setLastTimeHook(null);
setCurrentHook(null);
}
// hook对外入口
export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
funcComp: (props: Props, arg: Arg) => any,
@ -57,9 +63,3 @@ export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
return comp;
}
function resetGlobalVariable() {
setHookStage(null);
setLastTimeHook(null);
setCurrentHook(null);
}

View File

@ -21,27 +21,17 @@ 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 {
// 异步触发的effect
useEffect(effectFunc, deps, EffectConstant.Effect);
}
function createEffect(effectFunc, removeFunc, deps, effectConstant): Effect {
const effect: Effect = {
effect: effectFunc,
removeEffect: removeFunc,
dependencies: deps,
effectConstant: effectConstant,
};
export function useLayoutEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null): void {
// 同步触发的effect
useEffect(effectFunc, deps, EffectConstant.LayoutEffect);
}
getProcessingVNode().effectList.push(effect);
function useEffect(effectFunc: () => (() => void) | void, deps: Array<any> | void | null, effectType: number): void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
if (stage === HookStage.Init) {
useEffectForInit(effectFunc, deps, effectType);
} else if (stage === HookStage.Update) {
useEffectForUpdate(effectFunc, deps, effectType);
}
return effect;
}
export function useEffectForInit(effectFunc, deps, effectType): void {
@ -76,15 +66,25 @@ export function useEffectForUpdate(effectFunc, deps, effectType): void {
hook.state = createEffect(effectFunc, removeFunc, nextDeps, EffectConstant.DepsChange | effectType);
}
function createEffect(effectFunc, removeFunc, deps, effectConstant): Effect {
const effect: Effect = {
effect: effectFunc,
removeEffect: removeFunc,
dependencies: deps,
effectConstant: effectConstant,
};
function useEffect(effectFunc: () => (() => void) | void, deps: Array<any> | void | null, effectType: number): void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
getProcessingVNode().effectList.push(effect);
return effect;
if (stage === HookStage.Init) {
useEffectForInit(effectFunc, deps, effectType);
} else if (stage === HookStage.Update) {
useEffectForUpdate(effectFunc, deps, effectType);
}
}
export function useEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null): void {
// 异步触发的effect
useEffect(effectFunc, deps, EffectConstant.Effect);
}
export function useLayoutEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null): void {
// 同步触发的effect
useEffect(effectFunc, deps, EffectConstant.LayoutEffect);
}

View File

@ -18,20 +18,6 @@ import { getHookStage } from './HookStage';
import { throwNotInFuncError } from './BaseHook';
import type { Ref } from './HookType';
export function useImperativeHandleImpl<R>(
ref: { current: R | null } | ((any) => any) | null | void,
func: () => R,
dependencies?: Array<any> | null
): void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
const params = isNotNull(dependencies) ? dependencies.concat([ref]) : null;
useLayoutEffectImpl(effectFunc.bind(null, func, ref), params);
}
function isNotNull(object: any): boolean {
return object !== null && object !== undefined;
}
@ -52,3 +38,17 @@ function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (()
};
}
}
export function useImperativeHandleImpl<R>(
ref: { current: R | null } | ((any) => any) | null | void,
func: () => R,
dependencies?: Array<any> | null
): void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
const params = isNotNull(dependencies) ? dependencies.concat([ref]) : null;
useLayoutEffectImpl(effectFunc.bind(null, func, ref), params);
}

View File

@ -22,29 +22,6 @@ import { getHookStage, HookStage } from './HookStage';
import type { VNode } from '../Types';
import { getProcessingVNode } from '../GlobalVar';
export function useReducerImpl<S, P, A>(
reducer: (S, A) => S,
initArg: P,
init?: (P) => S,
isUseState?: boolean
): [S, Trigger<A>] | void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
if (stage === HookStage.Init) {
return useReducerForInit(reducer, initArg, init, isUseState);
} else if (stage === HookStage.Update) {
// 获取当前的hook
const currentHook = getCurrentHook();
// 获取currentHook的更新数组
const currentHookUpdates = (currentHook.state as Reducer<S, A>).updates;
return updateReducerHookState(currentHookUpdates, currentHook, reducer);
}
}
// 构造新的Update数组
function insertUpdate<S, A>(action: A, hook: Hook<S, A>): Update<S, A> {
const newUpdate: Update<S, A> = {
@ -116,6 +93,25 @@ export function useReducerForInit<S, A>(reducer, initArg, init, isUseState?: boo
return [hook.state.stateValue, trigger];
}
// 计算stateValue值
function calculateNewState<S, A>(currentHookUpdates: Array<Update<S, A>>, currentHook, reducer: (S, A) => S) {
const reducerObj = currentHook.state;
let state = reducerObj.stateValue;
// 循环遍历更新数组,计算新的状态值
currentHookUpdates.forEach(update => {
// 1. didCalculated = true 说明state已经计算过; 2. 如果来自 isUseState
if (update.didCalculated && reducerObj.isUseState) {
state = update.state;
} else {
const action = update.action;
state = reducer(state, action);
}
});
return state;
}
// 更新hook.state
function updateReducerHookState<S, A>(currentHookUpdates, currentHook, reducer): [S, Trigger<A>] {
if (currentHookUpdates !== null) {
@ -135,21 +131,25 @@ function updateReducerHookState<S, A>(currentHookUpdates, currentHook, reducer):
return [currentHook.state.stateValue, currentHook.state.trigger];
}
// 计算stateValue值
function calculateNewState<S, A>(currentHookUpdates: Array<Update<S, A>>, currentHook, reducer: (S, A) => S) {
const reducerObj = currentHook.state;
let state = reducerObj.stateValue;
export function useReducerImpl<S, P, A>(
reducer: (S, A) => S,
initArg: P,
init?: (P) => S,
isUseState?: boolean
): [S, Trigger<A>] | void {
const stage = getHookStage();
if (stage === null) {
throwNotInFuncError();
}
// 循环遍历更新数组,计算新的状态值
currentHookUpdates.forEach(update => {
// 1. didCalculated = true 说明state已经计算过; 2. 如果来自 isUseState
if (update.didCalculated && reducerObj.isUseState) {
state = update.state;
} else {
const action = update.action;
state = reducer(state, action);
}
});
if (stage === HookStage.Init) {
return useReducerForInit(reducer, initArg, init, isUseState);
} else if (stage === HookStage.Update) {
// 获取当前的hook
const currentHook = getCurrentHook();
// 获取currentHook的更新数组
const currentHookUpdates = (currentHook.state as Reducer<S, A>).updates;
return state;
return updateReducerHookState(currentHookUpdates, currentHook, reducer);
}
}

View File

@ -40,28 +40,6 @@ export function isSchedulingEffects() {
return isScheduling;
}
export function callUseEffects(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
if (effectList !== null) {
effectList.forEach(effect => {
const { effectConstant } = effect;
if (
(effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect &&
(effectConstant & EffectConstant.DepsChange) !== EffectConstant.NoEffect
) {
hookEffects.push(effect);
hookRemoveEffects.push(effect);
// 异步调用
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
}
}
});
}
}
export function runAsyncEffects() {
const preMode = copyExecuteMode();
changeMode(InRender, true);
@ -98,6 +76,28 @@ export function runAsyncEffects() {
setExecuteMode(preMode);
}
export function callUseEffects(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
if (effectList !== null) {
effectList.forEach(effect => {
const { effectConstant } = effect;
if (
(effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect &&
(effectConstant & EffectConstant.DepsChange) !== EffectConstant.NoEffect
) {
hookEffects.push(effect);
hookRemoveEffects.push(effect);
// 异步调用
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
}
}
});
}
}
// 在销毁vNode的时候调用remove
export function callEffectRemove(vNode: VNode) {
const effectList: EffectList = vNode.effectList;

View File

@ -154,18 +154,6 @@ function hideOrUnhideAllChildren(vNode, isHidden) {
);
}
function attachRef(vNode: VNode) {
const ref = vNode.ref;
handleRef(vNode, ref, vNode.realNode);
}
function detachRef(vNode: VNode, isOldRef?: boolean) {
const ref = isOldRef ? vNode.oldRef : vNode.ref;
handleRef(vNode, ref, null);
}
function handleRef(vNode: VNode, ref, val) {
if (ref !== null && ref !== undefined) {
const refType = typeof ref;
@ -182,6 +170,18 @@ function handleRef(vNode: VNode, ref, val) {
}
}
function attachRef(vNode: VNode) {
const ref = vNode.ref;
handleRef(vNode, ref, vNode.realNode);
}
function detachRef(vNode: VNode, isOldRef?: boolean) {
const ref = isOldRef ? vNode.oldRef : vNode.ref;
handleRef(vNode, ref, null);
}
// 卸载一个vNode不会递归
function unmountVNode(vNode: VNode): void {
switch (vNode.tag) {
@ -217,6 +217,9 @@ function unmountVNode(vNode: VNode): void {
unmountDomComponents(vNode);
break;
}
default: {
break;
}
}
}
@ -413,6 +416,9 @@ function submitUpdate(vNode: VNode): void {
listenToPromise(vNode);
break;
}
default: {
break;
}
}
}

View File

@ -41,63 +41,6 @@ const LOOPING_UPDATE_LIMIT = 50;
let loopingUpdateCount = 0;
let lastRoot: VNode | null = null;
export function submitToRender(treeRoot) {
treeRoot.shouldUpdate = treeRoot.childShouldUpdate;
// 置空task让才能加入新的render任务
treeRoot.task = null;
const startVNode = getStartVNode();
if (FlagUtils.hasAnyFlag(startVNode)) {
// 把自己加上
if (startVNode.dirtyNodes === null) {
startVNode.dirtyNodes = [startVNode];
} else {
startVNode.dirtyNodes.push(startVNode);
}
}
const dirtyNodes = startVNode.dirtyNodes;
if (dirtyNodes !== null && dirtyNodes.length) {
const preMode = copyExecuteMode();
changeMode(InRender, true);
prepareForSubmit();
// before submit阶段
beforeSubmit(dirtyNodes);
// submit阶段
submit(dirtyNodes);
resetAfterSubmit();
// after submit阶段
afterSubmit(dirtyNodes);
setExecuteMode(preMode);
dirtyNodes.length = 0;
startVNode.dirtyNodes = null;
}
if (isSchedulingEffects()) {
setSchedulingEffects(false);
}
// 统计root同步重渲染的次数如果太多可能是无线循环
countLoopingUpdate(treeRoot);
// 在退出`submit` 之前始终调用此函数以确保任何已计划在此根上执行的update被执行。
tryRenderFromRoot(treeRoot);
if (rootThrowError) {
const error = rootThrowError;
rootThrowError = null;
throw error;
}
return null;
}
function beforeSubmit(dirtyNodes: Array<VNode>) {
let node;
const nodesLength = dirtyNodes.length;
@ -214,3 +157,60 @@ export function checkLoopingUpdateLimit() {
);
}
}
export function submitToRender(treeRoot) {
treeRoot.shouldUpdate = treeRoot.childShouldUpdate;
// 置空task让才能加入新的render任务
treeRoot.task = null;
const startVNode = getStartVNode();
if (FlagUtils.hasAnyFlag(startVNode)) {
// 把自己加上
if (startVNode.dirtyNodes === null) {
startVNode.dirtyNodes = [startVNode];
} else {
startVNode.dirtyNodes.push(startVNode);
}
}
const dirtyNodes = startVNode.dirtyNodes;
if (dirtyNodes !== null && dirtyNodes.length) {
const preMode = copyExecuteMode();
changeMode(InRender, true);
prepareForSubmit();
// before submit阶段
beforeSubmit(dirtyNodes);
// submit阶段
submit(dirtyNodes);
resetAfterSubmit();
// after submit阶段
afterSubmit(dirtyNodes);
setExecuteMode(preMode);
dirtyNodes.length = 0;
startVNode.dirtyNodes = null;
}
if (isSchedulingEffects()) {
setSchedulingEffects(false);
}
// 统计root同步重渲染的次数如果太多可能是无线循环
countLoopingUpdate(treeRoot);
// 在退出`submit` 之前始终调用此函数以确保任何已计划在此根上执行的update被执行。
tryRenderFromRoot(treeRoot);
if (rootThrowError) {
const error = rootThrowError;
rootThrowError = null;
throw error;
}
return null;
}

View File

@ -27,6 +27,14 @@ export function isOverTime() {
return false;
}
function asyncCall() {
if (isTestRuntime) {
setTimeout(callRenderTasks, 0);
} else {
port2.postMessage(null);
}
}
// 1、设置deadline2、回调TaskExecutor传过来的browserCallback
const callRenderTasks = () => {
if (browserCallback === null) {
@ -61,14 +69,6 @@ if (typeof MessageChannel === 'function') {
isTestRuntime = true;
}
function asyncCall() {
if (isTestRuntime) {
setTimeout(callRenderTasks, 0);
} else {
port2.postMessage(null);
}
}
export function requestBrowserCallback(callback) {
browserCallback = callback;

View File

@ -27,16 +27,6 @@ let callingQueueTask: any | null = null;
// 防止重入
let isCallingRenderQueue = false;
export function callRenderQueueImmediate() {
if (callingQueueTask !== null) {
// 取消异步调度
cancelTask(callingQueueTask);
callingQueueTask = null;
}
callRenderQueue();
}
// 执行render回调
function callRenderQueue() {
if (!isCallingRenderQueue && renderQueue !== null) {
@ -58,6 +48,16 @@ function callRenderQueue() {
}
}
export function callRenderQueueImmediate() {
if (callingQueueTask !== null) {
// 取消异步调度
cancelTask(callingQueueTask);
callingQueueTask = null;
}
callRenderQueue();
}
export function pushRenderCallback(callback: RenderCallback) {
if (renderQueue === null) {
renderQueue = [callback];

View File

@ -200,6 +200,8 @@ export class VNode {
break;
case Profiler:
break;
default:
break;
}
}
}

View File

@ -194,6 +194,8 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
vNode.updates = [];
break;
default:
break;
}
return vNode;

View File

@ -169,13 +169,6 @@ export function findDOMByClassInst(inst) {
return domVNode !== null ? domVNode.realNode : null;
}
// 判断dom树是否已经挂载
export function isMounted(vNode: VNode) {
const rootNode = getTreeRootVNode(vNode);
// 如果根节点是 Dom 类型节点,表示已经挂载
return rootNode.tag === TreeRoot;
}
function getTreeRootVNode(vNode) {
let node = vNode;
while (node.parent) {
@ -184,6 +177,13 @@ function getTreeRootVNode(vNode) {
return node;
}
// 判断dom树是否已经挂载
export function isMounted(vNode: VNode) {
const rootNode = getTreeRootVNode(vNode);
// 如果根节点是 Dom 类型节点,表示已经挂载
return rootNode.tag === TreeRoot;
}
// 找到相邻的DOM
export function getSiblingDom(vNode: VNode): Element | null {
let node: VNode = vNode;