Skip to content

Commit

Permalink
feat(okam-core): optimize ant array data operation
Browse files Browse the repository at this point in the history
  • Loading branch information
wuhy committed Nov 13, 2018
1 parent f6d7c1c commit 20be465
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 88 deletions.
37 changes: 21 additions & 16 deletions packages/okam-core/src/ant/base/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,7 @@

import componentBase from '../../base/component';

/**
* Emit custom component event
*
* @param {...any} args the event arguments
*/
componentBase.methods.$emit = function (...args) {
this.__beforeEmit && this.__beforeEmit(args);
this.$listener.emit.apply(this.$listener, args);

let eventProp = args[0];
eventProp = 'on' + eventProp.charAt(0).toUpperCase() + eventProp.substr(1);
let eventHandler = this.props[eventProp];
eventHandler.call(this, args[1]);
};

export default Object.assign(componentBase, {
const antComponent = Object.assign({}, componentBase, {
didMount() {
this.created();
this.attached();
Expand All @@ -38,3 +23,23 @@ export default Object.assign(componentBase, {
this.detached();
}
});

antComponent.methods = Object.assign({}, antComponent.methods, {

/**
* Emit custom component event
*
* @param {...any} args the event arguments
*/
$emit(...args) {
this.__beforeEmit && this.__beforeEmit(args);
this.$listener.emit.apply(this.$listener, args);

let eventProp = args[0];
eventProp = 'on' + eventProp.charAt(0).toUpperCase() + eventProp.substr(1);
let eventHandler = this.props[eventProp];
eventHandler.call(this, args[1]);
}
});

export default antComponent;
1 change: 1 addition & 0 deletions packages/okam-core/src/base/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default Object.assign({}, component, {
* @param {Object} query the page query params
*/
onLoad(query) {
this.$isPage = true;
this.$query = query || {};

// call component create life cycle method
Expand Down
45 changes: 42 additions & 3 deletions packages/okam-core/src/extend/data/observable/Observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ export function proxyObject(observer, data, root) {
*
* @param {Observer} observer the observer to observe array
* @param {Array} arr the array data to proxy
* @param {boolean} isPage whether is page component
* @return {Array}
*/
export function proxyArray(observer, arr) {
export function proxyArray(observer, arr, isPage) {
let newArr = [];
makeArrayObservable(newArr, observer);
makeArrayObservable(newArr, observer, isPage);

// XXX: copy array
// we cannot proxy array element visited by index, so we should not proxy array element by default
Expand Down Expand Up @@ -85,6 +86,41 @@ export default class Observer {
this.selector = getDataSelector(this.paths);
}

/**
* Set context data
*
* @private
* @param {*} value the value to set
*/
setContextData(value) {
let paths = this.paths;
let result = this.ctx.data;
let lastIdx = paths.length - 1;
for (let i = 0; i < lastIdx; i++) {
let p = paths[i];
result = result[p];
}

/* istanbul ignore next */
if (lastIdx >= 0) {
result[paths[lastIdx]] = value;
}
}

/**
* Get context data
*
* @return {*}
*/
getContextData() {
let paths = this.paths;
let result = this.ctx.data;
for (let i = 0, len = paths.length; i < len; i++) {
result = result[paths[i]];
}
return result;
}

/**
* Add dependence to current target computed property
*
Expand Down Expand Up @@ -121,7 +157,7 @@ export default class Observer {
if (Array.isArray(value)) {
paths || (paths = this.getPaths(k));
let observer = new Observer(ctx, value, paths, this.isProps);
return (observeData[k] = proxyArray(observer, value));
return (observeData[k] = proxyArray(observer, value, ctx.$isPage));
}
else if (value && typeof value === 'object') {
paths || (paths = this.getPaths(k));
Expand Down Expand Up @@ -189,6 +225,9 @@ export default class Observer {

this.rawData[k] = val;
}
else {
this.setContextData(this.rawData);
}

this.ctx.$setData({[selector]: val});
this.notifyWatcher(val, oldVal, paths);
Expand Down
81 changes: 81 additions & 0 deletions packages/okam-core/src/extend/data/observable/ant/array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @file Array data update proxy for ant application
* @author [email protected]
*/

'use strict';

/* eslint-disable fecs-export-on-declare */

const componentApi = {
__spliceData(path, spliceArgs, observer) {
let spliceInfo = {[path]: spliceArgs};
this.$spliceData(spliceInfo, this.__nextTickCallback);
// update the cache raw data
observer.rawData = observer.getContextData();
}
};

const observableArray = {
push(observer, rawPush, ...items) {
let {ctx, selector} = observer;

ctx.__spliceData(selector, [this.length, 0, ...items], observer);

return rawPush.apply(this, items);
},

shift(observer, rawShift) {
let {ctx, selector} = observer;
if (!this.length) {
return rawShift.call(this);
}

ctx.__spliceData(selector, [0, 1], observer);

return rawShift.call(this);
},

unshift(observer, rawUnshift, ...items) {
let {ctx, selector} = observer;
ctx.__spliceData(selector, [0, 0, ...items], observer);

return rawUnshift.apply(this, items);
},

pop(observer, rawPop) {
let {ctx, selector} = observer;
let len = this.length;
if (!len) {
return rawPop.call(this);
}
ctx.__spliceData(selector, [len - 1, 1], observer);

return rawPop.call(this);
},

splice(observer, rawSplice, ...args) {
let {ctx, selector} = observer;
ctx.__spliceData(selector, args, observer);

return rawSplice.apply(this, args);
}
};

Object.keys(observableArray).forEach(k => {
let raw = observableArray[k];
observableArray[k] = function (...args) {
let observer = args[0];
observer.ctx.__dataUpTaskNum++;
let result = raw.apply(this, args);

observer.notifyWatcher(this, this, observer.paths);

return result;
};
});

export {
observableArray as array,
componentApi as component
};
38 changes: 36 additions & 2 deletions packages/okam-core/src/extend/data/observable/ant/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,42 @@

'use strict';

import observable, {setPropDataKey} from '../index';
import observable, {setObservableContext} from '../index';
import {observableArray, overrideArrayMethods} from '../array';
import {component as antApi, array as antArray} from './array';

setPropDataKey('props');
setObservableContext('props', true);

Object.assign(observable.component.methods, antApi);

let arrApis = Object.assign({}, observableArray, antArray);
overrideArrayMethods(arrApis, true);
overrideArrayMethods(arrApis, false);

/**
* View update hook
*
* @private
* @param {Object} prevProps the previous property data before update
*/
observable.component.didUpdate = function (prevProps) {
let propObserver = this.__propsObserver;
if (!propObserver) {
return;
}

let currProps = this.props;
// update the cache props data, as for the prop data will be override
// when prop change, it leads to the cache props data will not refer to
// the new props data
propObserver.rawData = currProps;
Object.keys(prevProps).forEach(k => {
let newVal = currProps[k];
let oldVal = prevProps[k];
if (newVal !== oldVal) {
propObserver.firePropValueChange(k, newVal, oldVal);
}
});
};

export default observable;
79 changes: 55 additions & 24 deletions packages/okam-core/src/extend/data/observable/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@

'use strict';

const hasProto = '__proto__' in {};

/**
* The default override Array APIs to proxy array data update
*
* @type {Object}
*/
export const observableArray = {
push(observer, rawPush, ...items) {
let rawData = observer.rawData;
Expand Down Expand Up @@ -80,6 +87,37 @@ export const observableArray = {
}
};

/**
* The Page Array APIs to override
*
* @inner
* @type {Object}
*/
let overridePageArrApis = observableArray;

/**
* The component Array APIs to override
*
* @inner
* @type {Object}
*/
let overrideComponentArrApis = observableArray;

/**
* Extend the array operation methods
*
* @param {Object} arrApis the array methods to override
* @param {boolean} isPage whether is page Array APIs to override
*/
export function overrideArrayMethods(arrApis, isPage) {
if (isPage) {
overridePageArrApis = arrApis;
}
else {
overrideComponentArrApis = arrApis;
}
}

/**
* Update array item value
*
Expand All @@ -103,41 +141,34 @@ function getArrayItem(observer, idx) {
return observer.get(idx);
}

let overrideArrApis = observableArray;

/**
* Extend the array operation methods
* Make array observable
*
* @param {Object} extension the array method extension
* @param {boolean} isOverride whether override default array extend apis,
* by default false, for test purpose
* @param {Array} arr the array to observe
* @param {Observer} observer the observer
* @param {boolean} isPage whether is page Array APIs to override
* @return {Array}
*/
export function extendArrayMethods(extension, isOverride) {
export default function makeArrayObservable(arr, observer, isPage) {
let arrayMethods;
/* istanbul ignore next */
if (isOverride) {
overrideArrApis = extension;
if (hasProto) {
arrayMethods = Object.create(Array.prototype);
/* eslint-disable no-proto */
arr.__proto__ = arrayMethods;
}
else {
/* istanbul ignore next */
Object.assign(overrideArrApis, extension);
arrayMethods = arr;
}
}

/**
* Make array observable
*
* @param {Array} arr the array to observe
* @param {Observer} observer the observer
* @return {Array}
*/
export default function makeArrayObservable(arr, observer) {
let overrideArrApis = isPage ? overridePageArrApis : overrideComponentArrApis;
Object.keys(overrideArrApis).forEach(method => {
let rawMethod = arr[method];
arr[method] = overrideArrApis[method].bind(arr, observer, rawMethod);
let rawMethod = arrayMethods[method];
arrayMethods[method] = overrideArrApis[method].bind(arr, observer, rawMethod);
});

arr.setItem = updateArrayItem.bind(arr, observer);
arr.getItem = getArrayItem.bind(arr, observer);
arrayMethods.setItem = updateArrayItem.bind(arr, observer);
arrayMethods.getItem = getArrayItem.bind(arr, observer);

return arr;
}
Loading

0 comments on commit 20be465

Please sign in to comment.