Match-id-63629d6cb470978c34a9bfafe90501013205792a
This commit is contained in:
commit
3f1eeba456
|
@ -73,7 +73,7 @@ function executeRender(children: any, container: Container, callback?: Callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
function findDOMNode(domOrEle?: Element): null | Element | Text {
|
function findDOMNode(domOrEle?: Element): null | Element | Text {
|
||||||
if (domOrEle == null) {
|
if (domOrEle === null || domOrEle === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ function removeRootEventLister(container: Container) {
|
||||||
|
|
||||||
// 卸载入口
|
// 卸载入口
|
||||||
function destroy(container: Container): boolean {
|
function destroy(container: Container): boolean {
|
||||||
if (container && container._treeRoot) {
|
if (container._treeRoot) {
|
||||||
syncUpdates(() => {
|
syncUpdates(() => {
|
||||||
executeRender(null, container, () => {
|
executeRender(null, container, () => {
|
||||||
removeRootEventLister(container);
|
removeRootEventLister(container);
|
||||||
|
|
|
@ -46,7 +46,7 @@ function getChildNS(parentNS: string | null, tagName: string): string {
|
||||||
return NSS.html;
|
return NSS.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentNS == null || parentNS === NSS.html) {
|
if (parentNS === null || parentNS === NSS.html) {
|
||||||
// 没有父命名空间,或父命名空间为xhtml
|
// 没有父命名空间,或父命名空间为xhtml
|
||||||
return NSS[tagName] ?? NSS.html;
|
return NSS[tagName] ?? NSS.html;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,8 @@ export function isTextChild(type: string, props: Props): boolean {
|
||||||
return (
|
return (
|
||||||
props.dangerouslySetInnerHTML &&
|
props.dangerouslySetInnerHTML &&
|
||||||
typeof props.dangerouslySetInnerHTML === 'object' &&
|
typeof props.dangerouslySetInnerHTML === 'object' &&
|
||||||
props.dangerouslySetInnerHTML.__html != null
|
props.dangerouslySetInnerHTML.__html !== null &&
|
||||||
|
props.dangerouslySetInnerHTML.__html !== undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +149,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
|
||||||
|
|
||||||
if (tag === DomComponent) {
|
if (tag === DomComponent) {
|
||||||
// DomComponent类型
|
// DomComponent类型
|
||||||
if (element != null) {
|
if (element !== null && element !== undefined) {
|
||||||
const type = vNode.type;
|
const type = vNode.type;
|
||||||
const changeList = vNode.changeList;
|
const changeList = vNode.changeList;
|
||||||
vNode.changeList = null;
|
vNode.changeList = null;
|
||||||
|
@ -158,7 +159,14 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
|
||||||
updateVNodeProps(element, newProps);
|
updateVNodeProps(element, newProps);
|
||||||
// 应用diff更新Properties.
|
// 应用diff更新Properties.
|
||||||
// 当一个选中的radio改变名称,浏览器使另一个radio的复选框为false.
|
// 当一个选中的radio改变名称,浏览器使另一个radio的复选框为false.
|
||||||
if (type === 'input' && newProps.type === 'radio' && newProps.name != null && newProps.checked != null) {
|
if (
|
||||||
|
type === 'input'
|
||||||
|
&& newProps.type === 'radio'
|
||||||
|
&& newProps.name !== null
|
||||||
|
&& newProps.name !== undefined
|
||||||
|
&& newProps.checked !== null
|
||||||
|
&& newProps.checked !== undefined
|
||||||
|
) {
|
||||||
updateCommonProp(element, 'checked', newProps.checked, true);
|
updateCommonProp(element, 'checked', newProps.checked, true);
|
||||||
}
|
}
|
||||||
const isNativeTag = isNativeElement(type, newProps);
|
const isNativeTag = isNativeElement(type, newProps);
|
||||||
|
@ -202,7 +210,7 @@ export function hideDom(tag: string, dom: Element | Text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不隐藏元素
|
// 不隐藏元素
|
||||||
export function unHideDom(tag: string, dom: Element | Text, props: Props) {
|
export function unHideDom(tag: string, dom: Element | Text, props?: Props) {
|
||||||
if (tag === DomComponent) {
|
if (tag === DomComponent) {
|
||||||
dom.style.display = adjustStyleValue('display', props?.style?.display ?? '');
|
dom.style.display = adjustStyleValue('display', props?.style?.display ?? '');
|
||||||
} else if (tag === DomText) {
|
} else if (tag === DomText) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ export function setDomProps(dom: Element, props: Object, isNativeTag: boolean, i
|
||||||
}
|
}
|
||||||
} else if (propName === 'dangerouslySetInnerHTML') {
|
} else if (propName === 'dangerouslySetInnerHTML') {
|
||||||
dom.innerHTML = propVal.__html;
|
dom.innerHTML = propVal.__html;
|
||||||
} else if (!isInit || propVal != null) {
|
} else if (!isInit || (propVal !== null && propVal !== undefined)) {
|
||||||
updateCommonProp(dom, propName, propVal, isNativeTag);
|
updateCommonProp(dom, propName, propVal, isNativeTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object {
|
||||||
for (let i = 0; i < oldPropsLength; i++) {
|
for (let i = 0; i < oldPropsLength; i++) {
|
||||||
propName = keysOfOldProps[i];
|
propName = keysOfOldProps[i];
|
||||||
// 新属性中包含该属性或者该属性为空值的属性不需要处理
|
// 新属性中包含该属性或者该属性为空值的属性不需要处理
|
||||||
if ( oldProps[propName] == null || keysOfNewProps.includes(propName)) {
|
if ( oldProps[propName] === null || oldProps[propName] === undefined || keysOfNewProps.includes(propName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,9 +103,13 @@ export function compareProps(oldProps: Object, newProps: Object): Object {
|
||||||
for (let i = 0; i < keysOfNewProps.length; i++) {
|
for (let i = 0; i < keysOfNewProps.length; i++) {
|
||||||
propName = keysOfNewProps[i];
|
propName = keysOfNewProps[i];
|
||||||
newPropValue = newProps[propName];
|
newPropValue = newProps[propName];
|
||||||
oldPropValue = oldProps != null ? oldProps[propName] : null;
|
oldPropValue = oldProps !== null && oldProps !== undefined ? oldProps[propName] : null;
|
||||||
|
|
||||||
if (newPropValue === oldPropValue || (newPropValue == null && oldPropValue == null)) {
|
if (
|
||||||
|
newPropValue === oldPropValue
|
||||||
|
|| ((newPropValue === null || newPropValue === undefined)
|
||||||
|
&& (oldPropValue === null || oldPropValue === undefined))
|
||||||
|
) {
|
||||||
// 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理
|
// 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +144,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object {
|
||||||
} else if (propName === 'dangerouslySetInnerHTML') {
|
} else if (propName === 'dangerouslySetInnerHTML') {
|
||||||
newHTML = newPropValue ? newPropValue.__html : undefined;
|
newHTML = newPropValue ? newPropValue.__html : undefined;
|
||||||
oldHTML = oldPropValue ? oldPropValue.__html : undefined;
|
oldHTML = oldPropValue ? oldPropValue.__html : undefined;
|
||||||
if (newHTML != null) {
|
if (newHTML !== null && newHTML !== undefined) {
|
||||||
if (oldHTML !== newHTML) {
|
if (oldHTML !== newHTML) {
|
||||||
toUpdateProps[propName] = newPropValue;
|
toUpdateProps[propName] = newPropValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ export function adjustStyleValue(name, value) {
|
||||||
|
|
||||||
if (typeof value === 'number' && value !== 0 && isNeedUnitCSS(name)) {
|
if (typeof value === 'number' && value !== 0 && isNeedUnitCSS(name)) {
|
||||||
validValue = `${value}px`;
|
validValue = `${value}px`;
|
||||||
} else if (value === '' || value == null || typeof value === 'boolean') {
|
} else if (value === '' || value === null || value === undefined || typeof value === 'boolean') {
|
||||||
validValue = '';
|
validValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ function setSelectionRange(dom: HTMLInputElement | HTMLTextAreaElement, range) {
|
||||||
const { start, end } = range;
|
const { start, end } = range;
|
||||||
let realEnd = end;
|
let realEnd = end;
|
||||||
|
|
||||||
if (realEnd == null) {
|
if (realEnd === null || realEnd === undefined) {
|
||||||
realEnd = start;
|
realEnd = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,44 +21,13 @@ import { BELONG_CLASS_VNODE_KEY } from '../renderer/vnode/VNode';
|
||||||
|
|
||||||
// 生成key
|
// 生成key
|
||||||
function getItemKey(item: any, index: number): string {
|
function getItemKey(item: any, index: number): string {
|
||||||
if (typeof item === 'object' && item !== null && item.key != null) {
|
if (typeof item === 'object' && item !== null && item.key !== null && item.key !== undefined) {
|
||||||
return '.$' + item.key;
|
return '.$' + item.key;
|
||||||
}
|
}
|
||||||
// 使用36进制减少生成字符串的长度以节省空间
|
// 使用36进制减少生成字符串的长度以节省空间
|
||||||
return '.' + index.toString(36);
|
return '.' + index.toString(36);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapChildrenToArray(children: any, arr: Array<any>, prefix: string, callback?: Function): number | void {
|
|
||||||
const type = typeof children;
|
|
||||||
switch (type) {
|
|
||||||
// 继承原有规格,undefined和boolean类型按照null处理
|
|
||||||
case 'undefined':
|
|
||||||
case 'boolean':
|
|
||||||
callMapFun(null, arr, prefix, callback);
|
|
||||||
return;
|
|
||||||
case 'number':
|
|
||||||
case 'string':
|
|
||||||
callMapFun(children, arr, prefix, callback);
|
|
||||||
return;
|
|
||||||
case 'object':
|
|
||||||
if (children === null) {
|
|
||||||
callMapFun(null, arr, prefix, callback);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const vtype = children.vtype;
|
|
||||||
if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) {
|
|
||||||
callMapFun(children, arr, prefix, callback);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Array.isArray(children)) {
|
|
||||||
processArrayChildren(children, arr, prefix, callback);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Error('Object is invalid as a Horizon child. ');
|
|
||||||
// No Default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processArrayChildren(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
function processArrayChildren(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
const childItem = children[i];
|
const childItem = children[i];
|
||||||
|
@ -93,6 +62,37 @@ function callMapFun(children: any, arr: Array<any>, prefix: string, callback: Fu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapChildrenToArray(children: any, arr: Array<any>, prefix: string, callback?: Function): number | void {
|
||||||
|
const type = typeof children;
|
||||||
|
switch (type) {
|
||||||
|
// 继承原有规格,undefined和boolean类型按照null处理
|
||||||
|
case 'undefined':
|
||||||
|
case 'boolean':
|
||||||
|
callMapFun(null, arr, prefix, callback);
|
||||||
|
return;
|
||||||
|
case 'number':
|
||||||
|
case 'string':
|
||||||
|
callMapFun(children, arr, prefix, callback);
|
||||||
|
return;
|
||||||
|
case 'object':
|
||||||
|
if (children === null) {
|
||||||
|
callMapFun(null, arr, prefix, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const vtype = children.vtype;
|
||||||
|
if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) {
|
||||||
|
callMapFun(children, arr, prefix, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Array.isArray(children)) {
|
||||||
|
processArrayChildren(children, arr, prefix, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error('Object is invalid as a Horizon child. ');
|
||||||
|
// No Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg
|
// 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg
|
||||||
function mapChildren(children: any, func: Function, context?: any): Array<any> {
|
function mapChildren(children: any, func: Function, context?: any): Array<any> {
|
||||||
if (children === null || children === undefined) {
|
if (children === null || children === undefined) {
|
||||||
|
|
|
@ -115,7 +115,8 @@ export function resolveMutation(from, to) {
|
||||||
if (res[i].mutation) found = true;
|
if (res[i].mutation) found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: resolve shifts
|
|
||||||
|
// need to resolve shifts
|
||||||
return { mutation: found, items: res, from, to };
|
return { mutation: found, items: res, from, to };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,8 @@ export function createStore(reducer: Reducer, preloadedState?: any, enhancers?):
|
||||||
}
|
}
|
||||||
|
|
||||||
export function combineReducers(reducers: { [key: string]: Reducer }): Reducer {
|
export function combineReducers(reducers: { [key: string]: Reducer }): Reducer {
|
||||||
return (state = {}, action) => {
|
return (state, action) => {
|
||||||
|
state = state || {};
|
||||||
const newState = {};
|
const newState = {};
|
||||||
Object.entries(reducers).forEach(([key, reducer]) => {
|
Object.entries(reducers).forEach(([key, reducer]) => {
|
||||||
newState[key] = reducer(state[key], action);
|
newState[key] = reducer(state[key], action);
|
||||||
|
|
|
@ -116,18 +116,22 @@ function makeStoreSnapshot({ type, data }) {
|
||||||
export const devtools = {
|
export const devtools = {
|
||||||
// returns vNode id from horizon devtools
|
// returns vNode id from horizon devtools
|
||||||
getVNodeId: vNode => {
|
getVNodeId: vNode => {
|
||||||
if (!isPanelActive()) return;
|
if (!isPanelActive()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
window['__HORIZON_DEV_HOOK__'].send(); // update list first
|
window['__HORIZON_DEV_HOOK__'].send(); // update list first
|
||||||
return window['__HORIZON_DEV_HOOK__'].getVnodeId(vNode);
|
return window['__HORIZON_DEV_HOOK__'].getVnodeId(vNode);
|
||||||
},
|
},
|
||||||
// sends horizonx devtool message to extension
|
// sends horizonx devtool message to extension
|
||||||
emit: (type, data) => {
|
emit: (type, data) => {
|
||||||
if (!isPanelActive()) return;
|
if (!isPanelActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
window.postMessage({
|
window.postMessage({
|
||||||
type: 'HORIZON_DEV_TOOLS',
|
type: 'HORIZON_DEV_TOOLS',
|
||||||
payload: makeStoreSnapshot({ type, data }),
|
payload: makeStoreSnapshot({ type, data }),
|
||||||
from: 'dev tool hook',
|
from: 'dev tool hook',
|
||||||
});
|
}, '');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,7 +139,7 @@ export const devtools = {
|
||||||
function getAffectedComponents() {
|
function getAffectedComponents() {
|
||||||
const allStores = getAllStores();
|
const allStores = getAllStores();
|
||||||
const keys = Object.keys(allStores);
|
const keys = Object.keys(allStores);
|
||||||
let res = {};
|
const res = {};
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
if (!allStores[key].$config.state._horizonObserver.keyVNodes) {
|
if (!allStores[key].$config.state._horizonObserver.keyVNodes) {
|
||||||
res[key] = [];
|
res[key] = [];
|
||||||
|
@ -144,17 +148,17 @@ function getAffectedComponents() {
|
||||||
const subRes = new Set();
|
const subRes = new Set();
|
||||||
const process = Array.from(allStores[key].$config.state._horizonObserver.keyVNodes.values());
|
const process = Array.from(allStores[key].$config.state._horizonObserver.keyVNodes.values());
|
||||||
while (process.length) {
|
while (process.length) {
|
||||||
let pivot = process.shift() as { tag: 'string' };
|
const pivot = process.shift() as { tag: 'string' };
|
||||||
if (pivot?.tag) subRes.add(pivot);
|
if (pivot.tag) subRes.add(pivot);
|
||||||
if (pivot?.toString() === '[object Set]') Array.from(pivot).forEach(item => process.push(item));
|
if (pivot.toString() === '[object Set]') Array.from(pivot).forEach(item => process.push(item));
|
||||||
}
|
}
|
||||||
res[key] = Array.from(subRes).map(vnode => {
|
res[key] = Array.from(subRes).map(vNode => {
|
||||||
return {
|
return {
|
||||||
name: vnode?.type
|
name: vNode?.type
|
||||||
.toString()
|
.toString()
|
||||||
.replace(/\{.*\}/, '{...}')
|
.replace(/\{.*\}/, '{...}')
|
||||||
.replace('function ', ''),
|
.replace('function ', ''),
|
||||||
nodeId: window.__HORIZON_DEV_HOOK__.getVnodeId(vnode),
|
nodeId: window.__HORIZON_DEV_HOOK__.getVnodeId(vNode),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -163,7 +167,7 @@ function getAffectedComponents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// listens to messages from background
|
// listens to messages from background
|
||||||
window.addEventListener('message', messageEvent => {
|
window.addEventListener('message', (messageEvent?) => {
|
||||||
if (messageEvent?.data?.payload?.type === 'horizonx request observed components') {
|
if (messageEvent?.data?.payload?.type === 'horizonx request observed components') {
|
||||||
// get observed components
|
// get observed components
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -171,7 +175,7 @@ window.addEventListener('message', messageEvent => {
|
||||||
type: 'HORIZON_DEV_TOOLS',
|
type: 'HORIZON_DEV_TOOLS',
|
||||||
payload: { type: OBSERVED_COMPONENTS, data: getAffectedComponents() },
|
payload: { type: OBSERVED_COMPONENTS, data: getAffectedComponents() },
|
||||||
from: 'dev tool hook',
|
from: 'dev tool hook',
|
||||||
});
|
}, '');
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +196,7 @@ window.addEventListener('message', messageEvent => {
|
||||||
const store = getStore(data.storeId);
|
const store = getStore(data.storeId);
|
||||||
if (!store?.[data.action]) return;
|
if (!store?.[data.action]) return;
|
||||||
|
|
||||||
const action = store.$queue?.[data.action];
|
const action = store.$queue[data.action];
|
||||||
const params = data.params;
|
const params = data.params;
|
||||||
action(...params);
|
action(...params);
|
||||||
}
|
}
|
||||||
|
@ -216,6 +220,7 @@ window.addEventListener('message', messageEvent => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO:implement add and delete element
|
|
||||||
|
// need to implement add and delete element
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,9 +41,6 @@ export class HooklessObserver implements IObserver {
|
||||||
|
|
||||||
triggerChangeListeners(mutation: any): void {
|
triggerChangeListeners(mutation: any): void {
|
||||||
this.listeners.forEach(listener => {
|
this.listeners.forEach(listener => {
|
||||||
if (!listener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
listener(mutation);
|
listener(mutation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ export class Observer implements IObserver {
|
||||||
const vNodes = this.keyVNodes.get(key);
|
const vNodes = this.keyVNodes.get(key);
|
||||||
//NOTE: using Set directly can lead to deadlock
|
//NOTE: using Set directly can lead to deadlock
|
||||||
const vNodeArray = Array.from(vNodes || []);
|
const vNodeArray = Array.from(vNodes || []);
|
||||||
vNodeArray?.forEach((vNode: VNode) => {
|
vNodeArray.forEach((vNode: VNode) => {
|
||||||
if (vNode.isStoreChange) {
|
if (vNode.isStoreChange) {
|
||||||
// VNode已经被触发过,不再重复触发
|
// VNode已经被触发过,不再重复触发
|
||||||
return;
|
return;
|
||||||
|
@ -97,10 +97,6 @@ export class Observer implements IObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerUpdate(vNode: VNode): void {
|
triggerUpdate(vNode: VNode): void {
|
||||||
if (!vNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 触发VNode更新
|
// 触发VNode更新
|
||||||
launchUpdateFromVNode(vNode);
|
launchUpdateFromVNode(vNode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function getObserver(rawObj: any): Observer {
|
||||||
return rawObj[OBSERVER_KEY];
|
return rawObj[OBSERVER_KEY];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createProxy(rawObj: any, isHookObserver = true, listener: { current: (...args) => any }): any {
|
export function createProxy(rawObj: any, listener: { current: (...args) => any }, isHookObserver = true): any {
|
||||||
// 不是对象(是原始数据类型)不用代理
|
// 不是对象(是原始数据类型)不用代理
|
||||||
if (!(rawObj && isObject(rawObj))) {
|
if (!(rawObj && isObject(rawObj))) {
|
||||||
return rawObj;
|
return rawObj;
|
||||||
|
@ -60,11 +60,12 @@ export function createProxy(rawObj: any, isHookObserver = true, listener: { curr
|
||||||
// 创建Proxy
|
// 创建Proxy
|
||||||
let proxyObj;
|
let proxyObj;
|
||||||
if (!isHookObserver) {
|
if (!isHookObserver) {
|
||||||
proxyObj = createObjectProxy(rawObj, true, {
|
proxyObj = createObjectProxy(rawObj, {
|
||||||
current: change => {
|
current: change => {
|
||||||
listener.current(change);
|
listener.current(change);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
true);
|
||||||
} else if (isArray(rawObj)) {
|
} else if (isArray(rawObj)) {
|
||||||
// 数组
|
// 数组
|
||||||
proxyObj = createArrayProxy(rawObj as [], {
|
proxyObj = createArrayProxy(rawObj as [], {
|
||||||
|
@ -74,18 +75,20 @@ export function createProxy(rawObj: any, isHookObserver = true, listener: { curr
|
||||||
});
|
});
|
||||||
} else if (isCollection(rawObj)) {
|
} else if (isCollection(rawObj)) {
|
||||||
// 集合
|
// 集合
|
||||||
proxyObj = createCollectionProxy(rawObj, true, {
|
proxyObj = createCollectionProxy(rawObj, {
|
||||||
current: change => {
|
current: change => {
|
||||||
listener.current(change);
|
listener.current(change);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
true);
|
||||||
} else {
|
} else {
|
||||||
// 原生对象 或 函数
|
// 原生对象 或 函数
|
||||||
proxyObj = createObjectProxy(rawObj, false, {
|
proxyObj = createObjectProxy(rawObj, {
|
||||||
current: change => {
|
current: change => {
|
||||||
listener?.current(change);
|
listener.current(change);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyMap.set(rawObj, proxyObj);
|
proxyMap.set(rawObj, proxyObj);
|
||||||
|
|
|
@ -97,7 +97,7 @@ export function createArrayProxy(rawObj: any[], listener: { current: (...args) =
|
||||||
// 对于value也需要进一步代理
|
// 对于value也需要进一步代理
|
||||||
const valProxy = singleLevel
|
const valProxy = singleLevel
|
||||||
? value
|
? value
|
||||||
: createProxy(value, hookObserverMap.get(rawObj), {
|
: createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
|
@ -108,7 +108,9 @@ export function createArrayProxy(rawObj: any[], listener: { current: (...args) =
|
||||||
listener.current(mutation);
|
listener.current(mutation);
|
||||||
listeners.forEach(lst => lst(mutation));
|
listeners.forEach(lst => lst(mutation));
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
|
|
||||||
return valProxy;
|
return valProxy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,17 +21,17 @@ import { createMapProxy } from './MapProxy';
|
||||||
|
|
||||||
export function createCollectionProxy(
|
export function createCollectionProxy(
|
||||||
rawObj: Object,
|
rawObj: Object,
|
||||||
hookObserver = true,
|
listener: { current: (...args) => any },
|
||||||
listener: { current: (...args) => any }
|
hookObserver = true
|
||||||
): Object {
|
): Object {
|
||||||
if (isWeakSet(rawObj)) {
|
if (isWeakSet(rawObj)) {
|
||||||
return createWeakSetProxy(rawObj, hookObserver, listener);
|
return createWeakSetProxy(rawObj, listener, hookObserver);
|
||||||
}
|
}
|
||||||
if (isSet(rawObj)) {
|
if (isSet(rawObj)) {
|
||||||
return createSetProxy(rawObj, hookObserver, listener);
|
return createSetProxy(rawObj, listener, hookObserver);
|
||||||
}
|
}
|
||||||
if (isWeakMap(rawObj)) {
|
if (isWeakMap(rawObj)) {
|
||||||
return createWeakMapProxy(rawObj, hookObserver, listener);
|
return createWeakMapProxy(rawObj, listener, hookObserver);
|
||||||
}
|
}
|
||||||
return createMapProxy(rawObj, hookObserver, listener);
|
return createMapProxy(rawObj, listener, hookObserver);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,17 @@ import { isPanelActive } from '../../devtools';
|
||||||
|
|
||||||
const COLLECTION_CHANGE = '_collectionChange';
|
const COLLECTION_CHANGE = '_collectionChange';
|
||||||
|
|
||||||
export function createMapProxy(rawObj: Object, hookObserver = true, listener: { current: (...args) => any }): Object {
|
export function createMapProxy(
|
||||||
|
rawObj: Object,
|
||||||
|
listener: { current: (...args) => any },
|
||||||
|
hookObserver = true
|
||||||
|
): Object {
|
||||||
let listeners: ((mutation) => {})[] = [];
|
let listeners: ((mutation) => {})[] = [];
|
||||||
let oldData: [any, any][] = [];
|
let oldData: [any, any][] = [];
|
||||||
let proxies = new Map();
|
let proxies = new Map();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
function getFun(rawObj: { get: (key: any) => any; has: (key: any) => boolean }, key: any) {
|
function getFun(rawObj: { get: (key: any) => any; has: (key: any) => boolean }, key: any): any {
|
||||||
const keyProxy = rawObj.has(key) ? key : proxies.get(key);
|
const keyProxy = rawObj.has(key) ? key : proxies.get(key);
|
||||||
if (!keyProxy) return;
|
if (!keyProxy) return;
|
||||||
const observer = getObserver(rawObj);
|
const observer = getObserver(rawObj);
|
||||||
|
@ -34,18 +38,20 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
const value = rawObj.get(keyProxy);
|
const value = rawObj.get(keyProxy);
|
||||||
|
|
||||||
// 对于value也需要进一步代理
|
// 对于value也需要进一步代理
|
||||||
const valProxy = createProxy(value, hookObserverMap.get(rawObj), {
|
const valProxy = createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, [key]: change.mutation.from },
|
{ ...rawObj, [key]: change.mutation.from },
|
||||||
{ ...rawObj, [key]: change.mutation.to }
|
{ ...rawObj, [key]: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
|
|
||||||
return valProxy;
|
return valProxy;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +66,7 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
},
|
},
|
||||||
key: any,
|
key: any,
|
||||||
value: any
|
value: any
|
||||||
) {
|
): any {
|
||||||
if (rawObj.has(key) || rawObj.has(proxies.get(key))) {
|
if (rawObj.has(key) || rawObj.has(proxies.get(key))) {
|
||||||
// VALUE CHANGE (whole value for selected key is changed)
|
// VALUE CHANGE (whole value for selected key is changed)
|
||||||
const oldValue = rawObj.get(proxies.get(key));
|
const oldValue = rawObj.get(proxies.get(key));
|
||||||
|
@ -70,7 +76,7 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
const observer = getObserver(rawObj);
|
const observer = getObserver(rawObj);
|
||||||
observer.setProp(COLLECTION_CHANGE, mutation);
|
observer.setProp(COLLECTION_CHANGE, mutation);
|
||||||
|
|
||||||
if (observer.watchers?.[key]) {
|
if (observer.watchers[key]) {
|
||||||
observer.watchers[key].forEach(cb => {
|
observer.watchers[key].forEach(cb => {
|
||||||
cb(key, oldValue, value, mutation);
|
cb(key, oldValue, value, mutation);
|
||||||
});
|
});
|
||||||
|
@ -80,19 +86,21 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
oldData = [...Array.from(rawObj.entries())];
|
oldData = [...Array.from(rawObj.entries())];
|
||||||
} else {
|
} else {
|
||||||
// NEW VALUE
|
// NEW VALUE
|
||||||
const keyProxy = createProxy(key, hookObserverMap.get(rawObj), {
|
const keyProxy = createProxy(key, {
|
||||||
current: change => {
|
current: change => {
|
||||||
// KEY CHANGE
|
// KEY CHANGE
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, ['_keyChange']: change.mutation.from },
|
{ ...rawObj, ['_keyChange']: change.mutation.from },
|
||||||
{ ...rawObj, ['_keyChange']: change.mutation.to }
|
{ ...rawObj, ['_keyChange']: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
proxies.set(key, keyProxy);
|
proxies.set(key, keyProxy);
|
||||||
|
|
||||||
rawObj.set(keyProxy, value);
|
rawObj.set(keyProxy, value);
|
||||||
|
@ -176,32 +184,36 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
const observer = getObserver(rawObj);
|
const observer = getObserver(rawObj);
|
||||||
observer.useProp(COLLECTION_CHANGE);
|
observer.useProp(COLLECTION_CHANGE);
|
||||||
rawObj.forEach((value, key) => {
|
rawObj.forEach((value, key) => {
|
||||||
const keyProxy = createProxy(value, hookObserverMap.get(rawObj), {
|
const keyProxy = createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
//KEY ATTRIBUTES CHANGED
|
//KEY ATTRIBUTES CHANGED
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, ['_keyChange']: change.mutation.from },
|
{ ...rawObj, ['_keyChange']: change.mutation.from },
|
||||||
{ ...rawObj, ['_keyChange']: change.mutation.to }
|
{ ...rawObj, ['_keyChange']: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
const valProxy = createProxy(key, hookObserverMap.get(rawObj), {
|
);
|
||||||
current: change => {
|
const valProxy = createProxy(key, {
|
||||||
// VALUE ATTRIBUTE CHANGED
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
// VALUE ATTRIBUTE CHANGED
|
||||||
change.parents.push(rawObj);
|
if (!change.parents) change.parents = [];
|
||||||
let mutation = resolveMutation(
|
change.parents.push(rawObj);
|
||||||
{ ...rawObj, key: change.mutation.from },
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, key: change.mutation.to }
|
{ ...rawObj, key: change.mutation.from },
|
||||||
);
|
{ ...rawObj, key: change.mutation.to }
|
||||||
listener.current({ ...change, mutation });
|
);
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listener.current({ ...change, mutation });
|
||||||
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
// 最后一个参数要返回代理对象
|
// 最后一个参数要返回代理对象
|
||||||
return callback(keyProxy, valProxy, rawObj);
|
return callback(keyProxy, valProxy, rawObj);
|
||||||
});
|
});
|
||||||
|
@ -217,18 +229,20 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
const { value, done } = rawIt.next();
|
const { value, done } = rawIt.next();
|
||||||
if (done) {
|
if (done) {
|
||||||
return {
|
return {
|
||||||
value: createProxy(value, hookObserver, {
|
value: createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, [value]: change.mutation.from },
|
{ ...rawObj, [value]: change.mutation.from },
|
||||||
{ ...rawObj, [value]: change.mutation.to }
|
{ ...rawObj, [value]: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
hookObserver
|
||||||
|
),
|
||||||
done,
|
done,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -238,45 +252,51 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
if (type === 'entries') {
|
if (type === 'entries') {
|
||||||
//ENTRY CHANGED
|
//ENTRY CHANGED
|
||||||
newVal = [
|
newVal = [
|
||||||
createProxy(value[0], hookObserver, {
|
createProxy(value[0], {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, ['itemChange']: { key: change.mutation.from, value: value[1] } },
|
{ ...rawObj, ['itemChange']: { key: change.mutation.from, value: value[1] } },
|
||||||
{ ...rawObj, ['itemChange']: { key: change.mutation.to, value: value[1] } }
|
{ ...rawObj, ['itemChange']: { key: change.mutation.to, value: value[1] } }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
hookObserver
|
||||||
createProxy(value[1], hookObserver, {
|
),
|
||||||
current: change => {
|
createProxy(value[1], {
|
||||||
if (!change.parents) change.parents = [];
|
current: change => {
|
||||||
change.parents.push(rawObj);
|
if (!change.parents) change.parents = [];
|
||||||
let mutation = resolveMutation(
|
change.parents.push(rawObj);
|
||||||
{ ...rawObj, item: { key: value[0], value: change.mutation.from } },
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, item: { key: value[0], value: change.mutation.to } }
|
{ ...rawObj, item: { key: value[0], value: change.mutation.from } },
|
||||||
);
|
{ ...rawObj, item: { key: value[0], value: change.mutation.to } }
|
||||||
listener.current({ ...change, mutation });
|
);
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listener.current({ ...change, mutation });
|
||||||
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
hookObserver
|
||||||
|
),
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
// SINGLE VALUE CHANGED
|
// SINGLE VALUE CHANGED
|
||||||
newVal = createProxy(value, hookObserver, {
|
newVal = createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.from },
|
{ ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.from },
|
||||||
{ ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.to }
|
{ ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserver
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { value: newVal, done };
|
return { value: newVal, done };
|
||||||
|
@ -314,6 +334,20 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
return wrapIterator(rawObj, rawObj.entries(), 'entries');
|
return wrapIterator(rawObj, rawObj.entries(), 'entries');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handler = {
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
delete: deleteFun,
|
||||||
|
clear,
|
||||||
|
has,
|
||||||
|
entries,
|
||||||
|
forEach,
|
||||||
|
keys,
|
||||||
|
values,
|
||||||
|
// 判断Symbol类型,兼容IE
|
||||||
|
[typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf,
|
||||||
|
};
|
||||||
|
|
||||||
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
||||||
if (key === 'size') {
|
if (key === 'size') {
|
||||||
return size(rawObj);
|
return size(rawObj);
|
||||||
|
@ -357,20 +391,6 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: {
|
||||||
return Reflect.get(rawObj, key, receiver);
|
return Reflect.get(rawObj, key, receiver);
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const handler = {
|
|
||||||
get,
|
|
||||||
set,
|
|
||||||
delete: deleteFun,
|
|
||||||
clear,
|
|
||||||
has,
|
|
||||||
entries,
|
|
||||||
forEach,
|
|
||||||
keys,
|
|
||||||
values,
|
|
||||||
// 判断Symbol类型,兼容IE
|
|
||||||
[typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf,
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
const boundHandler = {};
|
const boundHandler = {};
|
||||||
Object.entries(handler).forEach(([id, val]) => {
|
Object.entries(handler).forEach(([id, val]) => {
|
||||||
boundHandler[id] = (...args: any[]) => {
|
boundHandler[id] = (...args: any[]) => {
|
||||||
|
|
|
@ -41,8 +41,8 @@ function set(rawObj: object, key: string, value: any, receiver: any): boolean {
|
||||||
|
|
||||||
export function createObjectProxy<T extends object>(
|
export function createObjectProxy<T extends object>(
|
||||||
rawObj: T,
|
rawObj: T,
|
||||||
singleLevel = false,
|
listener: { current: (...args) => any },
|
||||||
listener: { current: (...args) => any }
|
singleLevel = false
|
||||||
): ProxyHandler<T> {
|
): ProxyHandler<T> {
|
||||||
let listeners = [] as ((...args) => void)[];
|
let listeners = [] as ((...args) => void)[];
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ export function createObjectProxy<T extends object>(
|
||||||
// 对于value也需要进一步代理
|
// 对于value也需要进一步代理
|
||||||
const valProxy = singleLevel
|
const valProxy = singleLevel
|
||||||
? value
|
? value
|
||||||
: createProxy(value, hookObserverMap.get(rawObj), {
|
: createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
|
@ -98,7 +98,9 @@ export function createObjectProxy<T extends object>(
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
|
|
||||||
return valProxy;
|
return valProxy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ const COLLECTION_CHANGE = '_collectionChange';
|
||||||
|
|
||||||
export function createSetProxy<T extends object>(
|
export function createSetProxy<T extends object>(
|
||||||
rawObj: T,
|
rawObj: T,
|
||||||
hookObserver = true,
|
listener: { current: (...args) => any },
|
||||||
listener: { current: (...args) => any }
|
hookObserver = true
|
||||||
): ProxyHandler<T> {
|
): ProxyHandler<T> {
|
||||||
let listeners: ((mutation) => {})[] = [];
|
let listeners: ((mutation) => {})[] = [];
|
||||||
let proxies = new WeakMap();
|
let proxies = new WeakMap();
|
||||||
|
@ -29,26 +29,28 @@ export function createSetProxy<T extends object>(
|
||||||
// Set的add方法
|
// Set的add方法
|
||||||
function add(rawObj: { add: (any) => void; has: (any) => boolean; values: () => any[] }, value: any): Object {
|
function add(rawObj: { add: (any) => void; has: (any) => boolean; values: () => any[] }, value: any): Object {
|
||||||
if (!rawObj.has(proxies.get(value))) {
|
if (!rawObj.has(proxies.get(value))) {
|
||||||
const proxy = createProxy(value, hookObserverMap.get(rawObj), {
|
const proxy = createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, valueChange: change.mutation.from },
|
{ ...rawObj, valueChange: change.mutation.from },
|
||||||
{ ...rawObj, valueChange: change.mutation.to }
|
{ ...rawObj, valueChange: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({
|
listener.current({
|
||||||
...change,
|
|
||||||
mutation,
|
|
||||||
});
|
|
||||||
listeners.forEach(lst =>
|
|
||||||
lst({
|
|
||||||
...change,
|
...change,
|
||||||
mutation,
|
mutation,
|
||||||
})
|
});
|
||||||
);
|
listeners.forEach(lst =>
|
||||||
|
lst({
|
||||||
|
...change,
|
||||||
|
mutation,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
const oldValues = Array.from(rawObj.values());
|
const oldValues = Array.from(rawObj.values());
|
||||||
|
|
||||||
proxies.set(value, proxy);
|
proxies.set(value, proxy);
|
||||||
|
@ -129,6 +131,20 @@ export function createSetProxy<T extends object>(
|
||||||
return rawObj.size;
|
return rawObj.size;
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const handler = {
|
||||||
|
get,
|
||||||
|
add,
|
||||||
|
delete: deleteFun,
|
||||||
|
has,
|
||||||
|
clear,
|
||||||
|
forEach,
|
||||||
|
forOf,
|
||||||
|
entries,
|
||||||
|
keys,
|
||||||
|
values,
|
||||||
|
[typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf,
|
||||||
|
};
|
||||||
|
|
||||||
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
||||||
if (Object.prototype.hasOwnProperty.call(handler, key)) {
|
if (Object.prototype.hasOwnProperty.call(handler, key)) {
|
||||||
const value = Reflect.get(handler, key, receiver);
|
const value = Reflect.get(handler, key, receiver);
|
||||||
|
@ -196,13 +212,13 @@ export function createSetProxy<T extends object>(
|
||||||
};
|
};
|
||||||
const { value, done } = rawIt.next();
|
const { value, done } = rawIt.next();
|
||||||
if (done) {
|
if (done) {
|
||||||
return { value: createProxy(value, hookObserver, currentListener), done };
|
return { value: createProxy(value, currentListener, hookObserver), done };
|
||||||
}
|
}
|
||||||
|
|
||||||
observer.useProp(COLLECTION_CHANGE);
|
observer.useProp(COLLECTION_CHANGE);
|
||||||
|
|
||||||
let newVal;
|
let newVal;
|
||||||
newVal = createProxy(value, hookObserver, currentListener);
|
newVal = createProxy(value, currentListener, hookObserver);
|
||||||
|
|
||||||
return { value: newVal, done };
|
return { value: newVal, done };
|
||||||
},
|
},
|
||||||
|
@ -260,27 +276,13 @@ export function createSetProxy<T extends object>(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const valProxy = createProxy(value, hookObserverMap.get(rawObj), currentListener);
|
const valProxy = createProxy(value, currentListener, hookObserverMap.get(rawObj));
|
||||||
const keyProxy = createProxy(key, hookObserverMap.get(rawObj), currentListener);
|
const keyProxy = createProxy(key, currentListener, hookObserverMap.get(rawObj));
|
||||||
// 最后一个参数要返回代理对象
|
// 最后一个参数要返回代理对象
|
||||||
return callback(valProxy, keyProxy, rawObj);
|
return callback(valProxy, keyProxy, rawObj);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const handler = {
|
|
||||||
get,
|
|
||||||
add,
|
|
||||||
delete: deleteFun,
|
|
||||||
has,
|
|
||||||
clear,
|
|
||||||
forEach,
|
|
||||||
forOf,
|
|
||||||
entries,
|
|
||||||
keys,
|
|
||||||
values,
|
|
||||||
[typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf,
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
getObserver(rawObj).addListener(change => {
|
getObserver(rawObj).addListener(change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
|
|
|
@ -22,11 +22,44 @@ const COLLECTION_CHANGE = '_collectionChange';
|
||||||
|
|
||||||
export function createWeakMapProxy(
|
export function createWeakMapProxy(
|
||||||
rawObj: Object,
|
rawObj: Object,
|
||||||
hookObserver = true,
|
listener: { current: (...args) => any },
|
||||||
listener: { current: (...args) => any }
|
hookObserver = true
|
||||||
): Object {
|
): Object {
|
||||||
let listeners: ((mutation) => {})[] = [];
|
let listeners: ((mutation) => {})[] = [];
|
||||||
|
|
||||||
|
const handler = {
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
add,
|
||||||
|
delete: deleteFun,
|
||||||
|
clear,
|
||||||
|
has,
|
||||||
|
};
|
||||||
|
|
||||||
|
function getFun(rawObj: { get: (key: any) => any }, key: any) {
|
||||||
|
const observer = getObserver(rawObj);
|
||||||
|
observer.useProp(key);
|
||||||
|
|
||||||
|
const value = rawObj.get(key);
|
||||||
|
// 对于value也需要进一步代理
|
||||||
|
const valProxy = createProxy(value, {
|
||||||
|
current: change => {
|
||||||
|
if (!change.parents) change.parents = [];
|
||||||
|
change.parents.push(rawObj);
|
||||||
|
let mutation = resolveMutation(
|
||||||
|
{ ...rawObj, [key]: change.mutation.from },
|
||||||
|
{ ...rawObj, [key]: change.mutation.to }
|
||||||
|
);
|
||||||
|
listener.current({ ...change, mutation });
|
||||||
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
|
|
||||||
|
return valProxy;
|
||||||
|
}
|
||||||
|
|
||||||
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
||||||
if (key === 'get') {
|
if (key === 'get') {
|
||||||
return getFun.bind(null, rawObj);
|
return getFun.bind(null, rawObj);
|
||||||
|
@ -66,28 +99,6 @@ export function createWeakMapProxy(
|
||||||
return Reflect.get(rawObj, key, receiver);
|
return Reflect.get(rawObj, key, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFun(rawObj: { get: (key: any) => any }, key: any) {
|
|
||||||
const observer = getObserver(rawObj);
|
|
||||||
observer.useProp(key);
|
|
||||||
|
|
||||||
const value = rawObj.get(key);
|
|
||||||
// 对于value也需要进一步代理
|
|
||||||
const valProxy = createProxy(value, hookObserverMap.get(rawObj), {
|
|
||||||
current: change => {
|
|
||||||
if (!change.parents) change.parents = [];
|
|
||||||
change.parents.push(rawObj);
|
|
||||||
let mutation = resolveMutation(
|
|
||||||
{ ...rawObj, [key]: change.mutation.from },
|
|
||||||
{ ...rawObj, [key]: change.mutation.to }
|
|
||||||
);
|
|
||||||
listener.current({ ...change, mutation });
|
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return valProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map的set方法
|
// Map的set方法
|
||||||
function set(
|
function set(
|
||||||
rawObj: { get: (key: any) => any; set: (key: any, value: any) => any; has: (key: any) => boolean },
|
rawObj: { get: (key: any) => any; set: (key: any, value: any) => any; has: (key: any) => boolean },
|
||||||
|
@ -171,15 +182,6 @@ export function createWeakMapProxy(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const handler = {
|
|
||||||
get,
|
|
||||||
set,
|
|
||||||
add,
|
|
||||||
delete: deleteFun,
|
|
||||||
clear,
|
|
||||||
has,
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
getObserver(rawObj).addListener(change => {
|
getObserver(rawObj).addListener(change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
|
|
|
@ -18,12 +18,19 @@ import { createProxy, getObserver, hookObserverMap } from '../ProxyHandler';
|
||||||
|
|
||||||
export function createWeakSetProxy<T extends object>(
|
export function createWeakSetProxy<T extends object>(
|
||||||
rawObj: T,
|
rawObj: T,
|
||||||
|
listener: { current: (...args) => any },
|
||||||
hookObserver = true,
|
hookObserver = true,
|
||||||
listener: { current: (...args) => any }
|
|
||||||
): ProxyHandler<T> {
|
): ProxyHandler<T> {
|
||||||
let listeners: ((mutation) => {})[] = [];
|
let listeners: ((mutation) => {})[] = [];
|
||||||
let proxies = new WeakMap();
|
let proxies = new WeakMap();
|
||||||
|
|
||||||
|
const handler = {
|
||||||
|
get,
|
||||||
|
add,
|
||||||
|
delete: deleteFun,
|
||||||
|
has,
|
||||||
|
};
|
||||||
|
|
||||||
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
function get(rawObj: { size: number }, key: any, receiver: any): any {
|
||||||
if (Object.prototype.hasOwnProperty.call(handler, key)) {
|
if (Object.prototype.hasOwnProperty.call(handler, key)) {
|
||||||
const value = Reflect.get(handler, key, receiver);
|
const value = Reflect.get(handler, key, receiver);
|
||||||
|
@ -59,18 +66,20 @@ export function createWeakSetProxy<T extends object>(
|
||||||
// Set的add方法
|
// Set的add方法
|
||||||
function add(rawObj: { add: (any) => void; has: (any) => boolean }, value: any): Object {
|
function add(rawObj: { add: (any) => void; has: (any) => boolean }, value: any): Object {
|
||||||
if (!rawObj.has(proxies.get(value))) {
|
if (!rawObj.has(proxies.get(value))) {
|
||||||
const proxy = createProxy(value, hookObserverMap.get(rawObj), {
|
const proxy = createProxy(value, {
|
||||||
current: change => {
|
current: change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
let mutation = resolveMutation(
|
let mutation = resolveMutation(
|
||||||
{ ...rawObj, [value]: change.mutation.from },
|
{ ...rawObj, [value]: change.mutation.from },
|
||||||
{ ...rawObj, [value]: change.mutation.to }
|
{ ...rawObj, [value]: change.mutation.to }
|
||||||
);
|
);
|
||||||
listener.current({ ...change, mutation });
|
listener.current({ ...change, mutation });
|
||||||
listeners.forEach(lst => lst({ ...change, mutation }));
|
listeners.forEach(lst => lst({ ...change, mutation }));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
hookObserverMap.get(rawObj)
|
||||||
|
);
|
||||||
|
|
||||||
proxies.set(value, proxy);
|
proxies.set(value, proxy);
|
||||||
|
|
||||||
|
@ -109,13 +118,6 @@ export function createWeakSetProxy<T extends object>(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const handler = {
|
|
||||||
get,
|
|
||||||
add,
|
|
||||||
delete: deleteFun,
|
|
||||||
has,
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
getObserver(rawObj).addListener(change => {
|
getObserver(rawObj).addListener(change => {
|
||||||
if (!change.parents) change.parents = [];
|
if (!change.parents) change.parents = [];
|
||||||
change.parents.push(rawObj);
|
change.parents.push(rawObj);
|
||||||
|
|
|
@ -161,7 +161,7 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
|
||||||
current: listener => {},
|
current: listener => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const proxyObj = createProxy(config.state, !config.options?.isReduxAdapter, listener);
|
const proxyObj = createProxy(config.state, listener, !config.options?.isReduxAdapter);
|
||||||
|
|
||||||
proxyObj.$pending = false;
|
proxyObj.$pending = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue