Match-id-6aa4ff44738c3e17ce4256de708591d0f487e7bb
This commit is contained in:
commit
4359db22f2
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
export function isObject(obj) {
|
||||
const type = typeof obj;
|
||||
return obj != null && (type === 'object' || type === 'function');
|
||||
}
|
||||
|
||||
export function isSet(obj) {
|
||||
return obj != null && (Object.prototype.toString.call(obj) === '[object Set]' || obj.constructor === Set);
|
||||
}
|
||||
|
||||
export function isWeakSet(obj) {
|
||||
return obj != null && (Object.prototype.toString.call(obj) === '[object WeakSet]' || obj.constructor === WeakSet);
|
||||
}
|
||||
|
||||
export function isMap(obj) {
|
||||
return obj != null && (Object.prototype.toString.call(obj) === '[object Map]' || obj.constructor === Map);
|
||||
}
|
||||
|
||||
export function isWeakMap(obj) {
|
||||
return obj != null && (Object.prototype.toString.call(obj) === '[object WeakMap]' || obj.constructor === WeakMap);
|
||||
}
|
||||
|
||||
export function isArray(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
}
|
||||
|
||||
export function isCollection(obj) {
|
||||
return isSet(obj) || isWeakSet(obj) || isMap(obj) || isWeakMap(obj);
|
||||
}
|
||||
|
||||
export function isString(obj) {
|
||||
return typeof obj === 'string';
|
||||
}
|
||||
|
||||
export function isValidIntegerKey(key) {
|
||||
return isString(key) && key !== 'NaN' && key[0] !== '-' && String(parseInt(key, 10)) === key;
|
||||
}
|
||||
|
||||
export const noop = () => {};
|
||||
|
||||
export function isSame(x, y) {
|
||||
if (!(typeof Object.is === 'function')) {
|
||||
if (x === y) {
|
||||
// +0 != -0
|
||||
return x !== 0 || 1 / x === 1 / y;
|
||||
} else {
|
||||
// NaN == NaN
|
||||
return x !== x && y !== y;
|
||||
}
|
||||
} else {
|
||||
return Object.is(x, y);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
export function isObject(obj: any): boolean {
|
||||
const type = typeof obj;
|
||||
return (obj !== null || obj !== undefined) && (type === 'object' || type === 'function');
|
||||
}
|
||||
|
||||
export function isSet(obj: any): boolean {
|
||||
return (obj !== null || obj !== undefined) && (Object.prototype.toString.call(obj) === '[object Set]' || obj.constructor === Set);
|
||||
}
|
||||
|
||||
export function isWeakSet(obj: any): boolean {
|
||||
return (obj !== null || obj !== undefined) && (Object.prototype.toString.call(obj) === '[object WeakSet]' || obj.constructor === WeakSet);
|
||||
}
|
||||
|
||||
export function isMap(obj: any): boolean {
|
||||
return (obj !== null || obj !== undefined) && (Object.prototype.toString.call(obj) === '[object Map]' || obj.constructor === Map);
|
||||
}
|
||||
|
||||
export function isWeakMap(obj: any): boolean {
|
||||
return (obj !== null || obj !== undefined) && (Object.prototype.toString.call(obj) === '[object WeakMap]' || obj.constructor === WeakMap);
|
||||
}
|
||||
|
||||
export function isArray(obj: any): boolean {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
}
|
||||
|
||||
export function isCollection(obj: any): boolean {
|
||||
return isSet(obj) || isWeakSet(obj) || isMap(obj) || isWeakMap(obj);
|
||||
}
|
||||
|
||||
export function isString(obj: any): boolean {
|
||||
return typeof obj === 'string';
|
||||
}
|
||||
|
||||
// key是有效的正整数字的字符串
|
||||
export function isValidIntegerKey(key: any): boolean {
|
||||
return isString(key) && key !== 'NaN' && key[0] !== '-' && String(parseInt(key, 10)) === key;
|
||||
}
|
||||
|
||||
export function isPromise(obj: any): boolean {
|
||||
return isObject(obj) && typeof obj.then === 'function';
|
||||
}
|
||||
|
||||
export function isSame(x, y) {
|
||||
if (!(typeof Object.is === 'function')) {
|
||||
if (x === y) {
|
||||
// +0 != -0
|
||||
return x !== 0 || 1 / x === 1 / y;
|
||||
} else {
|
||||
// NaN == NaN
|
||||
return x !== x && y !== y;
|
||||
}
|
||||
} else {
|
||||
return Object.is(x, y);
|
||||
}
|
||||
}
|
|
@ -13,8 +13,4 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
// The two constants must be the same as those in horizon.
|
||||
export const FunctionComponent = 'FunctionComponent';
|
||||
export const ClassComponent = 'ClassComponent';
|
||||
|
||||
export const OBSERVER_KEY = '_horizonObserver';
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
import { createStore as createStoreX } from '../store/StoreHandler';
|
||||
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler';
|
||||
|
||||
export { thunk } from './reduxThunk';
|
||||
|
||||
export {
|
||||
|
@ -29,6 +27,14 @@ export {
|
|||
createDispatchHook,
|
||||
} from './reduxReact';
|
||||
|
||||
export type ReduxStoreHandler = {
|
||||
reducer: (state: any, action: { type: string }) => any;
|
||||
dispatch: (action: { type: string }) => void;
|
||||
getState: () => any;
|
||||
subscribe: (listener: () => void) => () => void;
|
||||
replaceReducer: (reducer: (state: any, action: { type: string }) => any) => void;
|
||||
};
|
||||
|
||||
export type ReduxAction = {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
import { useState, useContext, useEffect, useRef } from '../../renderer/hooks/HookExternal';
|
||||
import { createContext } from '../../renderer/components/context/CreateContext';
|
||||
import { createElement } from '../../external/JSXElement';
|
||||
import { BoundActionCreator } from './redux';
|
||||
import { ReduxAction } from './redux';
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler';
|
||||
import type { ReduxStoreHandler, ReduxAction, BoundActionCreator } from './redux';
|
||||
|
||||
const DefaultContext = createContext(null);
|
||||
type Context = typeof DefaultContext;
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
import { ReduxAction, ReduxMiddleware } from './redux';
|
||||
import { ReduxStoreHandler } from '../store/StoreHandler';
|
||||
import { ReduxStoreHandler, ReduxAction, ReduxMiddleware } from './redux';
|
||||
|
||||
function createThunkMiddleware(extraArgument?: any): ReduxMiddleware {
|
||||
return (store: ReduxStoreHandler) =>
|
||||
|
|
|
@ -17,7 +17,6 @@ import { IObserver } from './Observer';
|
|||
|
||||
/**
|
||||
* 一个对象(对象、数组、集合)对应一个Observer
|
||||
*
|
||||
*/
|
||||
export class HooklessObserver implements IObserver {
|
||||
listeners: (() => void)[] = [];
|
||||
|
|
|
@ -13,14 +13,10 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 一个对象(对象、数组、集合)对应一个Observer
|
||||
*/
|
||||
|
||||
//@ts-ignore
|
||||
import { launchUpdateFromVNode } from '../../renderer/TreeBuilder';
|
||||
import { getProcessingVNode } from '../../renderer/GlobalVar';
|
||||
import { VNode } from '../../renderer/vnode/VNode';
|
||||
|
||||
export interface IObserver {
|
||||
useProp: (key: string) => void;
|
||||
|
||||
|
@ -39,6 +35,9 @@ export interface IObserver {
|
|||
clearByVNode: (vNode: any) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个对象(对象、数组、集合)对应一个Observer
|
||||
*/
|
||||
export class Observer implements IObserver {
|
||||
vNodeKeys = new WeakMap();
|
||||
|
||||
|
@ -48,16 +47,18 @@ export class Observer implements IObserver {
|
|||
|
||||
watchers = {} as { [key: string]: ((key: string, oldValue: any, newValue: any) => void)[] };
|
||||
|
||||
// 对象的属性被使用时调用
|
||||
useProp(key: string | symbol): void {
|
||||
const processingVNode = getProcessingVNode();
|
||||
if (processingVNode === null || !processingVNode.observers) {
|
||||
// 异常场景
|
||||
return;
|
||||
}
|
||||
|
||||
// vNode -> Observers
|
||||
processingVNode.observers.add(this);
|
||||
|
||||
// key -> vNodes
|
||||
// key -> vNodes,记录这个prop被哪些VNode使用了
|
||||
let vNodes = this.keyVNodes.get(key);
|
||||
if (!vNodes) {
|
||||
vNodes = new Set();
|
||||
|
@ -65,7 +66,7 @@ export class Observer implements IObserver {
|
|||
}
|
||||
vNodes.add(processingVNode);
|
||||
|
||||
// vNode -> keys
|
||||
// vNode -> keys,记录这个VNode使用了哪些props
|
||||
let keys = this.vNodeKeys.get(processingVNode);
|
||||
if (!keys) {
|
||||
keys = new Set();
|
||||
|
@ -74,6 +75,32 @@ export class Observer implements IObserver {
|
|||
keys.add(key);
|
||||
}
|
||||
|
||||
// 对象的属性被赋值时调用
|
||||
setProp(key: string | symbol): void {
|
||||
const vNodes = this.keyVNodes.get(key);
|
||||
vNodes?.forEach((vNode: VNode) => {
|
||||
if (vNode.isStoreChange) {
|
||||
// VNode已经被触发过,不再重复触发
|
||||
return;
|
||||
}
|
||||
vNode.isStoreChange = true;
|
||||
|
||||
// 触发vNode更新
|
||||
this.triggerUpdate(vNode);
|
||||
});
|
||||
|
||||
this.triggerChangeListeners();
|
||||
}
|
||||
|
||||
triggerUpdate(vNode: VNode): void {
|
||||
if (!vNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 触发VNode更新
|
||||
launchUpdateFromVNode(vNode);
|
||||
}
|
||||
|
||||
addListener(listener: () => void): void {
|
||||
this.listeners.push(listener);
|
||||
}
|
||||
|
@ -82,32 +109,11 @@ export class Observer implements IObserver {
|
|||
this.listeners = this.listeners.filter(item => item != listener);
|
||||
}
|
||||
|
||||
setProp(key: string | symbol): void {
|
||||
const vNodes = this.keyVNodes.get(key);
|
||||
vNodes?.forEach((vNode: VNode) => {
|
||||
if (vNode.isStoreChange) {
|
||||
// update already triggered
|
||||
return;
|
||||
}
|
||||
vNode.isStoreChange = true;
|
||||
|
||||
// 触发vNode更新
|
||||
this.triggerUpdate(vNode);
|
||||
});
|
||||
this.triggerChangeListeners();
|
||||
}
|
||||
|
||||
triggerChangeListeners(): void {
|
||||
this.listeners.forEach(listener => listener());
|
||||
}
|
||||
|
||||
triggerUpdate(vNode: VNode): void {
|
||||
if (!vNode) {
|
||||
return;
|
||||
}
|
||||
launchUpdateFromVNode(vNode);
|
||||
}
|
||||
|
||||
// 触发所有使用的props的VNode更新
|
||||
allChange(): void {
|
||||
const keyIt = this.keyVNodes.keys();
|
||||
let keyItem = keyIt.next();
|
||||
|
@ -117,6 +123,7 @@ export class Observer implements IObserver {
|
|||
}
|
||||
}
|
||||
|
||||
// 删除keyVNodes中保存的这个VNode的关系数据
|
||||
clearByVNode(vNode: VNode): void {
|
||||
const keys = this.vNodeKeys.get(vNode);
|
||||
if (keys) {
|
||||
|
|
|
@ -22,16 +22,18 @@ import { createCollectionProxy } from './handlers/CollectionProxyHandler';
|
|||
import { IObserver } from '../types';
|
||||
import { OBSERVER_KEY } from '../Constants';
|
||||
|
||||
// 保存rawObj -> Proxy
|
||||
const proxyMap = new WeakMap();
|
||||
|
||||
export const hookObserverMap = new WeakMap();
|
||||
|
||||
export function createProxy(rawObj: any, hookObserver = true): any {
|
||||
export function createProxy(rawObj: any, isHookObserver = true): any {
|
||||
// 不是对象(是原始数据类型)不用代理
|
||||
if (!isObject(rawObj)) {
|
||||
return rawObj;
|
||||
}
|
||||
|
||||
// 已代理过
|
||||
const existProxy = proxyMap.get(rawObj);
|
||||
if (existProxy) {
|
||||
return existProxy;
|
||||
|
@ -45,15 +47,15 @@ export function createProxy(rawObj: any, hookObserver = true): any {
|
|||
// 创建Observer
|
||||
let observer: IObserver = getObserver(rawObj);
|
||||
if (!observer) {
|
||||
observer = hookObserver ? new Observer() : new HooklessObserver();
|
||||
observer = isHookObserver ? new Observer() : new HooklessObserver();
|
||||
rawObj[OBSERVER_KEY] = observer;
|
||||
}
|
||||
|
||||
hookObserverMap.set(rawObj, hookObserver);
|
||||
hookObserverMap.set(rawObj, isHookObserver);
|
||||
|
||||
// 创建Proxy
|
||||
let proxyObj;
|
||||
if (!hookObserver) {
|
||||
if (!isHookObserver) {
|
||||
proxyObj = createObjectProxy(rawObj, true);
|
||||
} else if (isArray(rawObj)) {
|
||||
// 数组
|
||||
|
|
|
@ -44,6 +44,7 @@ function get(rawObj: any[], key: string, receiver: any) {
|
|||
if (isValidIntegerKey(key) || key === 'length') {
|
||||
return objectGet(rawObj, key, receiver);
|
||||
}
|
||||
|
||||
return Reflect.get(rawObj, key, receiver);
|
||||
}
|
||||
|
||||
|
@ -58,16 +59,19 @@ function set(rawObj: any[], key: string, value: any, receiver: any) {
|
|||
const observer = getObserver(rawObj);
|
||||
|
||||
if (!isSame(newValue, oldValue)) {
|
||||
// 值不一样,触发监听器
|
||||
if (observer.watchers?.[key]) {
|
||||
observer.watchers[key].forEach(cb => {
|
||||
cb(key, oldValue, newValue);
|
||||
});
|
||||
}
|
||||
|
||||
// 触发属性变化
|
||||
observer.setProp(key);
|
||||
}
|
||||
|
||||
if (oldLength !== newLength) {
|
||||
// 触发数组的大小变化
|
||||
observer.setProp('length');
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
|
||||
import { isObject } from '../CommonUtils';
|
||||
|
||||
export function readonlyProxy<T extends object>(target: T): ProxyHandler<T> {
|
||||
return new Proxy(target, {
|
||||
get(target, property, receiver) {
|
||||
const result = Reflect.get(target, property, receiver);
|
||||
export function readonlyProxy<T extends object>(rawObj: T): ProxyHandler<T> {
|
||||
return new Proxy(rawObj, {
|
||||
get(rawObj, property, receiver) {
|
||||
const result = Reflect.get(rawObj, property, receiver);
|
||||
|
||||
try {
|
||||
if (isObject(result)) {
|
||||
return readonlyProxy(result);
|
||||
|
|
|
@ -21,35 +21,33 @@ import readonlyProxy from '../proxy/readonlyProxy';
|
|||
import { Observer } from '../proxy/Observer';
|
||||
import { FunctionComponent, ClassComponent } from '../../renderer/vnode/VNodeTags';
|
||||
import { VNode } from '../../renderer/Types';
|
||||
import { isPromise } from '../CommonUtils';
|
||||
|
||||
const storeMap = new Map<string, StoreHandler<any, any, any>>();
|
||||
|
||||
function isPromise(obj: any): boolean {
|
||||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
|
||||
}
|
||||
|
||||
type StoreConfig<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>> = {
|
||||
id?: string;
|
||||
state?: S;
|
||||
actions?: A;
|
||||
id?: string;
|
||||
computed?: C;
|
||||
options?: any;
|
||||
};
|
||||
|
||||
export type ReduxStoreHandler = {
|
||||
reducer: (state: any, action: { type: string }) => any;
|
||||
dispatch: (action: { type: string }) => void;
|
||||
getState: () => any;
|
||||
subscribe: (listener: () => void) => () => void;
|
||||
replaceReducer: (reducer: (state: any, action: { type: string }) => any) => void;
|
||||
};
|
||||
type UserActions<S extends object> = { [K: string]: ActionFunction<S> };
|
||||
type ActionFunction<S extends object> = (this: StoreHandler<S, any, any>, state: S, ...args: any[]) => any;
|
||||
type StoreActions<S extends object, A extends UserActions<S>> = { [K in keyof A]: Action<A[K], S> };
|
||||
type Action<T extends ActionFunction<any>, S extends object> = (
|
||||
this: StoreHandler<S, any, any>,
|
||||
...args: RemoveFirstFromTuple<Parameters<T>>
|
||||
) => ReturnType<T>;
|
||||
|
||||
type StoreHandler<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>> = {
|
||||
$subscribe: (listener: () => void) => void;
|
||||
$unsubscribe: (listener: () => void) => void;
|
||||
$s: S;
|
||||
$queue: QueuedStoreActions<S, A>;
|
||||
$a: StoreActions<S, A>;
|
||||
$c: UserComputedValues<S>;
|
||||
$queue: QueuedStoreActions<S, A>;
|
||||
$subscribe: (listener: () => void) => void;
|
||||
$unsubscribe: (listener: () => void) => void;
|
||||
} & { [K in keyof S]: S[K] } & { [K in keyof A]: Action<A[K], S> } & { [K in keyof C]: ReturnType<C[K]> };
|
||||
|
||||
type PlannedAction<S extends object, F extends ActionFunction<S>> = {
|
||||
|
@ -63,41 +61,35 @@ type RemoveFirstFromTuple<T extends any[]> = T['length'] extends 0
|
|||
? I
|
||||
: [];
|
||||
|
||||
type UserActions<S extends object> = { [K: string]: ActionFunction<S> };
|
||||
type UserComputedValues<S extends object> = { [K: string]: ComputedFunction<S> };
|
||||
|
||||
type ActionFunction<S extends object> = (this: StoreHandler<S, any, any>, state: S, ...args: any[]) => any;
|
||||
type ComputedFunction<S extends object> = (state: S) => any;
|
||||
type Action<T extends ActionFunction<any>, S extends object> = (
|
||||
this: StoreHandler<S, any, any>,
|
||||
...args: RemoveFirstFromTuple<Parameters<T>>
|
||||
) => ReturnType<T>;
|
||||
|
||||
type AsyncAction<T extends ActionFunction<any>, S extends object> = (
|
||||
this: StoreHandler<S, any, any>,
|
||||
...args: RemoveFirstFromTuple<Parameters<T>>
|
||||
) => Promise<ReturnType<T>>;
|
||||
|
||||
type StoreActions<S extends object, A extends UserActions<S>> = { [K in keyof A]: Action<A[K], S> };
|
||||
type QueuedStoreActions<S extends object, A extends UserActions<S>> = { [K in keyof A]: AsyncAction<A[K], S> };
|
||||
type ComputedValues<S extends object, C extends UserComputedValues<S>> = { [K in keyof C]: ReturnType<C[K]> };
|
||||
|
||||
export function createStore<S extends object, A extends UserActions<S>, C extends UserComputedValues<S>>(
|
||||
config: StoreConfig<S, A, C>
|
||||
storeConfig: StoreConfig<S, A, C>
|
||||
): () => StoreHandler<S, A, C> {
|
||||
// create a local shalow copy to ensure consistency (if user would change the config object after store creation)
|
||||
config = {
|
||||
id: config.id,
|
||||
options: config.options,
|
||||
state: config.state,
|
||||
actions: config.actions ? { ...config.actions } : undefined,
|
||||
computed: config.computed ? { ...config.computed } : undefined,
|
||||
};
|
||||
|
||||
// 校验
|
||||
if (Object.prototype.toString.call(config) !== '[object Object]') {
|
||||
if (Object.prototype.toString.call(storeConfig) !== '[object Object]') {
|
||||
throw new Error('store obj must be pure object');
|
||||
}
|
||||
|
||||
// 创建本地浅拷贝以确保一致性(避免用户在创建存储后更改配置对象)
|
||||
const config = {
|
||||
id: storeConfig.id,
|
||||
state: storeConfig.state,
|
||||
actions: storeConfig.actions ? { ...storeConfig.actions } : undefined,
|
||||
computed: storeConfig.computed ? { ...storeConfig.computed } : undefined,
|
||||
options: storeConfig.options
|
||||
};
|
||||
|
||||
const proxyObj = createProxy(config.state, !config.options?.reduxAdapter);
|
||||
|
||||
proxyObj.$pending = false;
|
||||
|
@ -114,14 +106,14 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
|
|||
const $a: Partial<StoreActions<S, A>> = {};
|
||||
const $queue: Partial<StoreActions<S, A>> = {};
|
||||
const $c: Partial<ComputedValues<S, C>> = {};
|
||||
const handler = {
|
||||
const storeHandler = {
|
||||
$s: proxyObj,
|
||||
$a: $a as StoreActions<S, A>,
|
||||
$c: $c as ComputedValues<S, C>,
|
||||
$queue: $queue as QueuedStoreActions<S, A>,
|
||||
$config: config,
|
||||
$subscribe,
|
||||
$unsubscribe,
|
||||
$a: $a as StoreActions<S, A>,
|
||||
$s: proxyObj,
|
||||
$c: $c as ComputedValues<S, C>,
|
||||
$config: config,
|
||||
$queue: $queue as QueuedStoreActions<S, A>,
|
||||
} as unknown as StoreHandler<S, A, C>;
|
||||
|
||||
function tryNextAction() {
|
||||
|
@ -132,7 +124,7 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
|
|||
|
||||
const nextAction = plannedActions.shift()!;
|
||||
const result = config.actions
|
||||
? config.actions[nextAction.action].bind(handler, proxyObj)(...nextAction.payload)
|
||||
? config.actions[nextAction.action].bind(storeHandler, proxyObj)(...nextAction.payload)
|
||||
: undefined;
|
||||
|
||||
if (isPromise(result)) {
|
||||
|
@ -153,7 +145,7 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
|
|||
return new Promise(resolve => {
|
||||
if (!proxyObj.$pending) {
|
||||
proxyObj.$pending = true;
|
||||
const result = config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
const result = config.actions![action].bind(storeHandler, proxyObj)(...payload);
|
||||
|
||||
if (isPromise(result)) {
|
||||
result.then(value => {
|
||||
|
@ -174,45 +166,50 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
|
|||
});
|
||||
};
|
||||
|
||||
// 让store.$a[action]可以访问到action方法
|
||||
($a as any)[action] = function Wrapped(...payload) {
|
||||
return config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
return config.actions![action].bind(storeHandler, proxyObj)(...payload);
|
||||
};
|
||||
|
||||
// direct store access
|
||||
Object.defineProperty(handler, action, {
|
||||
// 让store[action]可以访问到action方法
|
||||
Object.defineProperty(storeHandler, action, {
|
||||
writable: false,
|
||||
value: (...payload) => {
|
||||
return config.actions![action].bind(handler, proxyObj)(...payload);
|
||||
return config.actions![action].bind(storeHandler, proxyObj)(...payload);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (config.computed) {
|
||||
Object.keys(config.computed).forEach(key => {
|
||||
($c as any)[key] = config.computed![key].bind(handler, readonlyProxy(proxyObj));
|
||||
Object.keys(config.computed).forEach(computeKey => {
|
||||
// 让store.$c[computeKey]可以访问到computed方法
|
||||
($c as any)[computeKey] = config.computed![computeKey].bind(storeHandler, readonlyProxy(proxyObj));
|
||||
|
||||
// direct store access
|
||||
Object.defineProperty(handler, key, {
|
||||
get: $c[key] as () => any,
|
||||
// 让store[computeKey]可以访问到computed的值
|
||||
Object.defineProperty(storeHandler, computeKey, {
|
||||
get: $c[computeKey] as () => any,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// direct state access
|
||||
// 让store[key]可以访问到state的值
|
||||
if (config.state) {
|
||||
Object.keys(config.state).forEach(key => {
|
||||
Object.defineProperty(handler, key, {
|
||||
get: () => proxyObj[key],
|
||||
Object.defineProperty(storeHandler, key, {
|
||||
get: () => {
|
||||
// 从Proxy对象获取值,会触发代理
|
||||
return proxyObj[key];
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (config.id) {
|
||||
storeMap.set(config.id, handler);
|
||||
storeMap.set(config.id, storeHandler);
|
||||
}
|
||||
|
||||
return createStoreHook(handler);
|
||||
return createStoreHook(storeHandler);
|
||||
}
|
||||
|
||||
export function clearVNodeObservers(vNode) {
|
||||
|
@ -238,8 +235,7 @@ function hookStore() {
|
|||
|
||||
if (processingVNode.tag === FunctionComponent) {
|
||||
// from FunctionComponent
|
||||
const vNodeRef = useRef(null) as unknown as { current: VNode };
|
||||
vNodeRef.current = processingVNode;
|
||||
const vNodeRef = useRef(processingVNode);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
|
|
@ -54,7 +54,7 @@ export type CallBack<F> = {
|
|||
};
|
||||
|
||||
export type Ref<V> = {
|
||||
current: V | null;
|
||||
current: V;
|
||||
};
|
||||
|
||||
export type Trigger<A> = (A) => void;
|
||||
|
|
Loading…
Reference in New Issue