Comparing version 0.1.0-alpha.9 to 0.2.0-alpha.0
{ | ||
"name": "okam-core", | ||
"version": "0.1.0-alpha.9", | ||
"version": "0.2.0-alpha.0", | ||
"description": "The extension for small program framework", | ||
@@ -16,3 +16,3 @@ "main": "index.js", | ||
"lint": "fecs ./src index.js --reporter=baidu --rule", | ||
"test": "NODE_ENV=development mocha --require babel-register test/tasks/**/*.spec.js" | ||
"test": "cross-env NODE_ENV=development mocha --require babel-register test/tasks/**/*.spec.js" | ||
}, | ||
@@ -24,2 +24,3 @@ "author": "wuhuiyao", | ||
"babel-plugin-espower": "^2.4.0", | ||
"cross-env": "^5.2.0", | ||
"mocha": "^5.2.0", | ||
@@ -26,0 +27,0 @@ "promise-polyfill": "^8.0.0" |
@@ -8,2 +8,3 @@ /** | ||
export * from '../App'; | ||
import App from '../App'; | ||
export default App; |
@@ -9,44 +9,12 @@ /** | ||
import {createComponent} from './helper/factory'; | ||
import componentBase from '../extend/component'; | ||
import antComponent from './extend/component'; | ||
import {normalizeComponent} from './helper/component'; | ||
import componentBase from './base/component'; | ||
function formatProps(props) { | ||
if (Array.isArray(props)) { | ||
return props.map(key => ({[key]: {}})); | ||
} | ||
let result = {}; | ||
// TODO: ant props only support default value setting? | ||
Object.keys(props).forEach(k => { | ||
let {type, default: value} = props[k]; | ||
if (typeof value === 'function') { | ||
type !== Function && (value = value()); | ||
} | ||
result[k] = value; | ||
}); | ||
return result; | ||
} | ||
function formatComponetInfo(componentInfo) { | ||
let {props, properties, mixins, behaviors} = componentInfo; | ||
if (!props && properties) { | ||
componentInfo.props = formatProps(properties); | ||
} | ||
if (behaviors && !mixins) { | ||
componentInfo.mixins = behaviors; | ||
} | ||
return componentInfo; | ||
} | ||
export default function extendComponent(componentInfo, refComponentIds) { | ||
export default function extendComponent(componentInfo, refComponents) { | ||
return createComponent( | ||
formatComponetInfo(componentInfo), | ||
antComponent, componentBase, | ||
{$refComponentIds: refComponentIds} | ||
componentInfo, | ||
componentBase, | ||
normalizeComponent, | ||
refComponents | ||
); | ||
} |
@@ -8,2 +8,3 @@ /** | ||
export * from '../Page'; | ||
import Page from '../Page'; | ||
export default Page; |
@@ -10,7 +10,32 @@ /** | ||
import {promisifyApis, interceptApis} from '../na/index'; | ||
import {mixin} from '../util/index'; | ||
export default mixin({}, { | ||
$type: 'app', | ||
/** | ||
* Initialize promisify APIs and interception APIs. | ||
* Return false, if inited. | ||
* | ||
* @inner | ||
* @return {boolean} | ||
*/ | ||
function initApis() { | ||
let promiseApis = this.$promisifyApis; | ||
let interceptAPis = this.$interceptApis; | ||
if (!this.__apisInited) { | ||
this.__apisInited = true; | ||
promisifyApis(promiseApis, this); | ||
interceptApis(interceptAPis, this.$api, this); | ||
let reqApiInterceptOpts = interceptAPis && interceptAPis.request; | ||
if (reqApiInterceptOpts) { | ||
interceptApis({request: reqApiInterceptOpts}, this.$http, this); | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
export default Object.assign({ | ||
/** | ||
@@ -22,3 +47,5 @@ * The hook when app launch | ||
onLaunch() { | ||
this.ready && this.ready(); | ||
let result = initApis.call(this); | ||
// ensure ready is called afther onShow for wx and after onLaunch for swan | ||
!result && this.ready && this.ready(); | ||
}, | ||
@@ -32,18 +59,6 @@ | ||
onShow() { | ||
let promiseApis = this.$promisifyApis; | ||
let interceptAPis = this.$interceptApis; | ||
if (!this.__apisInited) { | ||
this.__apisInited = true; | ||
promisifyApis(promiseApis, this); | ||
interceptApis(interceptAPis, this.$api, this); | ||
let reqApiInterceptOpts = interceptAPis && interceptAPis.request; | ||
if (reqApiInterceptOpts) { | ||
interceptApis({request: reqApiInterceptOpts}, this.$http, this); | ||
} | ||
} | ||
let result = initApis.call(this); | ||
!result && this.ready && this.ready(); | ||
} | ||
}, base); | ||
@@ -9,3 +9,2 @@ /** | ||
import {env, getCurrApp} from '../na/index'; | ||
import {mixin} from '../util/index'; | ||
import EventListener from '../util/EventListener'; | ||
@@ -75,55 +74,5 @@ import base from './base'; | ||
export default mixin({ | ||
$type: 'component', | ||
export default { | ||
/** | ||
* Emit custom component event | ||
* | ||
* @param {...any} args the event arguments | ||
*/ | ||
$emit(...args) { | ||
args = normalizeEventArgs.call(this, args); | ||
this.$listener.emit.apply(this.$listener, args); | ||
let triggerEvent = this.triggerEvent; | ||
if (triggerEvent) { | ||
triggerEvent.apply(this, args); | ||
} | ||
}, | ||
/** | ||
* Add the handler for the given event name to listen | ||
* | ||
* @param {string} eventName the event name to listen | ||
* @param {Function} handler the callback to listen | ||
*/ | ||
$on(eventName, handler) { | ||
this.$listener.on(eventName, handler); | ||
}, | ||
/** | ||
* Remove the handler for the given event name to listen. | ||
* If the eventName and handler are both not prvoided, it'll remove all event listeners. | ||
* If the eventName provided and the handler is not provided, it'll remove | ||
* the given event all listeners. | ||
* | ||
* @param {string} eventName the event name to listen | ||
* @param {Function} handler the callback to listen | ||
*/ | ||
$off(eventName, handler) { | ||
this.$listener.off(eventName, handler); | ||
}, | ||
/** | ||
* Add the handler for the given event name. The handler will be only triggered | ||
* once, after trigger once, the listener will be automatically removed. | ||
* | ||
* @param {*} eventName the event name to listen | ||
* @param {*} handler the event handler | ||
*/ | ||
$once(eventName, handler) { | ||
this.$listener.once(eventName, handler); | ||
}, | ||
/** | ||
* The created hook when component is created | ||
@@ -136,2 +85,3 @@ * | ||
this.$app = getCurrApp(); | ||
Object.assign(this, base); | ||
@@ -176,3 +126,3 @@ // call beforeCreate hook | ||
// call beforeDestroy hook | ||
this.beforeDestroy && this.beforeDstroy(); | ||
this.beforeDestroy && this.beforeDestroy(); | ||
@@ -190,2 +140,51 @@ this.$listener.off(); | ||
/** | ||
* Emit custom component event | ||
* | ||
* @param {...any} args the event arguments | ||
*/ | ||
$emit(...args) { | ||
args = normalizeEventArgs.call(this, args); | ||
this.$listener.emit.apply(this.$listener, args); | ||
let triggerEvent = this.triggerEvent; | ||
if (triggerEvent) { | ||
triggerEvent.apply(this, args); | ||
} | ||
}, | ||
/** | ||
* Add the handler for the given event name to listen | ||
* | ||
* @param {string} eventName the event name to listen | ||
* @param {Function} handler the callback to listen | ||
*/ | ||
$on(eventName, handler) { | ||
this.$listener.on(eventName, handler); | ||
}, | ||
/** | ||
* Remove the handler for the given event name to listen. | ||
* If the eventName and handler are both not prvoided, it'll remove all event listeners. | ||
* If the eventName provided and the handler is not provided, it'll remove | ||
* the given event all listeners. | ||
* | ||
* @param {string} eventName the event name to listen | ||
* @param {Function} handler the callback to listen | ||
*/ | ||
$off(eventName, handler) { | ||
this.$listener.off(eventName, handler); | ||
}, | ||
/** | ||
* Add the handler for the given event name. The handler will be only triggered | ||
* once, after trigger once, the listener will be automatically removed. | ||
* | ||
* @param {*} eventName the event name to listen | ||
* @param {*} handler the event handler | ||
*/ | ||
$once(eventName, handler) { | ||
this.$listener.once(eventName, handler); | ||
}, | ||
/** | ||
* The template event proxy handler | ||
@@ -226,2 +225,2 @@ * | ||
} | ||
}, base); | ||
}; |
@@ -11,3 +11,2 @@ /** | ||
export default Object.assign({}, component, { | ||
$type: 'page', | ||
@@ -46,3 +45,7 @@ /** | ||
this.detached(); | ||
} | ||
}, | ||
methods: Object.assign( | ||
{}, component.methods | ||
) | ||
}); |
@@ -8,52 +8,13 @@ /** | ||
import {createComponent} from './helper/factory'; | ||
import {normalizeComponent} from './helper/component'; | ||
import componentBase from './base/component'; | ||
import {createComponent} from './helper/factory'; | ||
function formatProps(props) { | ||
if (Array.isArray(props)) { | ||
return props.map(key => ({[key]: {type: null}})); | ||
} | ||
let result = {}; | ||
Object.keys(props).forEach(k => { | ||
let {type, observer, default: value} = props[k]; | ||
if (typeof value === 'function') { | ||
value = value(); | ||
} | ||
result[k] = { | ||
type, | ||
value, | ||
observer | ||
}; | ||
}); | ||
return result; | ||
} | ||
function formatComponetInfo(componentInfo) { | ||
let {props, properties, mixins, behaviors} = componentInfo; | ||
if (!properties && props) { | ||
componentInfo.props = componentInfo.properties = formatProps(props); | ||
} | ||
// 由于 底层会把 data 合入到 props,因此这里缓存下原始定义 | ||
props = componentInfo.props; | ||
if (props) { | ||
componentInfo.$rawProps = Object.assign({}, props); | ||
} | ||
if (!behaviors && mixins) { | ||
componentInfo.behaviors = mixins; | ||
} | ||
return componentInfo; | ||
} | ||
export default function extendComponent(componentInfo, refComponents) { | ||
return createComponent( | ||
formatComponetInfo(componentInfo), | ||
componentInfo, | ||
componentBase, | ||
normalizeComponent, | ||
refComponents | ||
); | ||
} |
@@ -12,3 +12,3 @@ /** | ||
const extension = { | ||
const broadcastAPIs = { | ||
$broadcast(...args) { | ||
@@ -74,10 +74,2 @@ eventCenter.emit.apply(eventCenter, args); | ||
this._bindBroadcastEvents = []; | ||
}, | ||
ready() { | ||
this.bindBroadcastEvents(); | ||
}, | ||
detached() { | ||
this.removeBroadcastEventListeners(); | ||
} | ||
@@ -87,3 +79,19 @@ }; | ||
export default { | ||
base: extension | ||
app: Object.assign({ | ||
ready() { | ||
this.bindBroadcastEvents(); | ||
} | ||
}, broadcastAPIs), | ||
component: { | ||
ready() { | ||
this.bindBroadcastEvents(); | ||
}, | ||
detached() { | ||
this.removeBroadcastEventListeners(); | ||
}, | ||
methods: broadcastAPIs | ||
} | ||
}; |
@@ -17,2 +17,4 @@ /** | ||
let idx = rawData.length; | ||
let result = rawPush.apply(this, items); | ||
items.forEach(data => { | ||
@@ -23,3 +25,3 @@ observer.set(idx, data); | ||
return rawPush.apply(this, items); | ||
return result; | ||
}, | ||
@@ -30,5 +32,7 @@ | ||
rawData.shift(); | ||
let result = rawShift.call(this); | ||
observer.set(null, rawData); | ||
return rawShift.call(this); | ||
return result; | ||
}, | ||
@@ -39,5 +43,7 @@ | ||
rawData.unshift(...items); | ||
let result = rawUnshift.apply(this, items); | ||
observer.set(null, rawData); | ||
return rawUnshift.apply(this, items); | ||
return result; | ||
}, | ||
@@ -48,5 +54,7 @@ | ||
rawData.pop(); | ||
let result = rawPop.call(this); | ||
observer.set(null, rawData); | ||
return rawPop.call(this); | ||
return result; | ||
}, | ||
@@ -57,5 +65,7 @@ | ||
rawSplice.apply(rawData, args); | ||
let result = rawSplice.apply(this, args); | ||
observer.set(null, rawData); | ||
return rawSplice.apply(this, args); | ||
return result; | ||
}, | ||
@@ -66,5 +76,7 @@ | ||
rawSort.apply(rawData, args); | ||
let result = rawSort.apply(this, args); | ||
observer.set(null, rawData); | ||
return rawSort.apply(this, args); | ||
return result; | ||
}, | ||
@@ -75,5 +87,7 @@ | ||
rawData.reverse(); | ||
let result = rawReverse.call(this); | ||
observer.set(null, rawData); | ||
return rawReverse.call(this); | ||
return result; | ||
} | ||
@@ -80,0 +94,0 @@ }, arrExtension); |
@@ -123,5 +123,7 @@ /** | ||
let computedInfo = this.computed; | ||
Object.keys(computedInfo).forEach( | ||
k => this.initDeps(k) | ||
); | ||
let result = {}; | ||
Object.keys(computedInfo).forEach(k => { | ||
result[k] = this.initDeps(k); | ||
}); | ||
this.ctx.$setData(result); | ||
} | ||
@@ -128,0 +130,0 @@ |
@@ -16,2 +16,6 @@ /** | ||
let computedInfo = ctx.computed || {}; | ||
if (typeof computedInfo === 'function') { | ||
ctx.computed = computedInfo = computedInfo(); | ||
} | ||
let observer = new ComputedObserver(ctx, computedInfo); | ||
@@ -32,2 +36,6 @@ let ctxProps = {}; | ||
let props = ctx.$rawProps; | ||
if (typeof props === 'function') { | ||
props = ctx.$rawProps = props(); | ||
} | ||
if (!props) { | ||
@@ -66,3 +74,6 @@ return; | ||
if (props) { | ||
ctx.$rawProps = Object.assign({}, props); | ||
// make the new added property accessible which must be added to | ||
// methods object and type must be function | ||
ctx.methods || (ctx.methods = {}); | ||
ctx.$rawProps = () => Object.assign({}, props); | ||
} | ||
@@ -84,97 +95,5 @@ | ||
export default { | ||
component: Object.assign({ | ||
component: { | ||
/** | ||
* Defer the callback to be executed after the next view updated cycle. | ||
* The callback context will be binded to the component instance | ||
* when executed. | ||
* | ||
* @param {Function} callback the callback to execute | ||
*/ | ||
$nextTick(callback) { | ||
let queues = this.$waitingDataUpQueues; | ||
if (queues) { | ||
queues.push(callback); | ||
} | ||
}, | ||
/** | ||
* Notify setData done | ||
* | ||
* @private | ||
*/ | ||
$notifySetDataDone() { | ||
if (this.$isDestroyed) { | ||
return; | ||
} | ||
let taskNum = this.__dataUpTaskNum; | ||
if (taskNum > 0) { | ||
this.__dataUpTaskNum--; | ||
return; | ||
} | ||
this.__dataUpTaskNum = 0; | ||
let queues = this.$waitingDataUpQueues; | ||
if (queues) { | ||
queues.forEach(callback => callback.call(this)); | ||
this.$waitingDataUpQueues = []; | ||
} | ||
// call lifecycle updated hook | ||
this.updated && this.updated(); | ||
}, | ||
/** | ||
* Execute setData operation to update view | ||
* | ||
* @private | ||
*/ | ||
$executeDataUpdate() { | ||
if (this.$isDestroyed) { | ||
return; | ||
} | ||
let queues = this.$upQueues; | ||
if (queues) { | ||
// call lifecycle beforeUpdate hook | ||
this.beforeUpdate && this.beforeUpdate(); | ||
this.setData(queues, this.__nextTickCallback); | ||
this.$upQueues = null; | ||
} | ||
}, | ||
/** | ||
* Set the view data. It'll not update the view immediatelly, it's deferred | ||
* to execute when enter the next event loop. | ||
* | ||
* @private | ||
* @param {string|Object} obj the data to set or the path to set | ||
* @param {*=} value the new value to set, optional | ||
*/ | ||
$setData(obj, value) { | ||
if (typeof obj === 'string') { | ||
obj = {[obj]: value}; | ||
} | ||
let queues = this.$upQueues; | ||
let isUpdating = !!queues; | ||
queues || (queues = this.$upQueues = {}); | ||
Object.assign(queues, obj); | ||
if (!isUpdating) { | ||
this.__dataUpTaskNum++; | ||
let handler = this.__executeDataUpdate; | ||
if (typeof Promise === 'function') { | ||
Promise.resolve().then(handler); | ||
} | ||
else { | ||
setTimeout(handler, 0); | ||
} | ||
} | ||
}, | ||
/** | ||
* The instance initialize before the instance is created. | ||
@@ -225,4 +144,99 @@ * | ||
this.__propsObserver = this.__computedObserver = null; | ||
} | ||
}, extendArrayApi) | ||
}, | ||
methods: Object.assign({ | ||
/** | ||
* Defer the callback to be executed after the next view updated cycle. | ||
* The callback context will be binded to the component instance | ||
* when executed. | ||
* | ||
* @param {Function} callback the callback to execute | ||
*/ | ||
$nextTick(callback) { | ||
let queues = this.$waitingDataUpQueues; | ||
if (queues) { | ||
queues.push(callback); | ||
} | ||
}, | ||
/** | ||
* Notify setData done | ||
* | ||
* @private | ||
*/ | ||
$notifySetDataDone() { | ||
if (this.$isDestroyed) { | ||
return; | ||
} | ||
let taskNum = this.__dataUpTaskNum; | ||
if (taskNum > 0) { | ||
this.__dataUpTaskNum--; | ||
return; | ||
} | ||
this.__dataUpTaskNum = 0; | ||
let queues = this.$waitingDataUpQueues; | ||
if (queues) { | ||
queues.forEach(callback => callback.call(this)); | ||
this.$waitingDataUpQueues = []; | ||
} | ||
// call lifecycle updated hook | ||
this.updated && this.updated(); | ||
}, | ||
/** | ||
* Execute setData operation to update view | ||
* | ||
* @private | ||
*/ | ||
$executeDataUpdate() { | ||
if (this.$isDestroyed) { | ||
return; | ||
} | ||
let queues = this.$upQueues; | ||
if (queues) { | ||
// call lifecycle beforeUpdate hook | ||
this.beforeUpdate && this.beforeUpdate(); | ||
this.setData(queues, this.__nextTickCallback); | ||
this.$upQueues = null; | ||
} | ||
}, | ||
/** | ||
* Set the view data. It'll not update the view immediatelly, it's deferred | ||
* to execute when enter the next event loop. | ||
* | ||
* @private | ||
* @param {string|Object} obj the data to set or the path to set | ||
* @param {*=} value the new value to set, optional | ||
*/ | ||
$setData(obj, value) { | ||
if (typeof obj === 'string') { | ||
obj = {[obj]: value}; | ||
} | ||
let queues = this.$upQueues; | ||
let isUpdating = !!queues; | ||
queues || (queues = this.$upQueues = {}); | ||
Object.assign(queues, obj); | ||
if (!isUpdating) { | ||
this.__dataUpTaskNum++; | ||
let handler = this.__executeDataUpdate; | ||
if (typeof Promise === 'function') { | ||
Promise.resolve().then(handler); | ||
} | ||
else { | ||
setTimeout(handler, 0); | ||
} | ||
} | ||
} | ||
}, extendArrayApi) | ||
} | ||
}; |
@@ -209,4 +209,4 @@ /** | ||
let oldVal = this.rawData[k]; | ||
if (val === oldVal) { | ||
let oldVal = k != null ? this.rawData[k] : this.rawData; | ||
if (k != null && val === oldVal) { | ||
return; | ||
@@ -213,0 +213,0 @@ } |
@@ -90,2 +90,5 @@ /** | ||
let upKeys = this.__storeComputedKeys; | ||
if (typeof upKeys === 'function') { | ||
this.__storeComputedKeys = upKeys = upKeys(); | ||
} | ||
if (observer && upKeys) { | ||
@@ -98,2 +101,5 @@ upKeys.forEach(k => observer.updateComputed(k)); | ||
let store = component.$store; | ||
if (!store) { | ||
return; | ||
} | ||
@@ -105,3 +111,2 @@ // init store computed state | ||
storeComputed && Object.assign(computed, storeComputed); | ||
storeComputed && (component.__storeComputedKeys = Object.keys(storeComputed)); | ||
@@ -113,4 +118,5 @@ // init store mutation actions | ||
actions && Object.assign(methods, actions); | ||
storeComputed && (methods.__storeComputedKeys = () => Object.keys(storeComputed)); | ||
return onStoreChange; | ||
} |
@@ -20,3 +20,4 @@ /** | ||
$init() { | ||
this.__storeChangeHandler = connect(this); | ||
let methods = this.methods; | ||
methods.__storeChangeHandler = connect(this); | ||
}, | ||
@@ -31,5 +32,7 @@ | ||
let store = this.$app.$store; | ||
this.__unsubscribeStore = store.subscribe( | ||
this.__storeChangeHandler.bind(this) | ||
); | ||
if (this.__storeChangeHandler) { | ||
this.__unsubscribeStore = store.subscribe( | ||
this.__storeChangeHandler.bind(this) | ||
); | ||
} | ||
this.$store = store; | ||
@@ -40,8 +43,34 @@ this.__state = store.getState(); | ||
/** | ||
* The beforeCreate hook | ||
* OnShow hook for page component | ||
* | ||
* @private | ||
*/ | ||
destroyed() { | ||
onShow() { | ||
if (this.__storeChangeHandler && !this.__unsubscribeStore) { | ||
this.__unsubscribeStore = this.$app.$store.subscribe( | ||
this.__storeChangeHandler.bind(this) | ||
); | ||
} | ||
}, | ||
/** | ||
* OnHide hook for page component | ||
* | ||
* @private | ||
*/ | ||
onHide() { | ||
let unsubscribe = this.__unsubscribeStore; | ||
if (unsubscribe) { | ||
unsubscribe(); | ||
this.__unsubscribeStore = null; | ||
} | ||
}, | ||
/** | ||
* The detached hook | ||
* | ||
* @private | ||
*/ | ||
detached() { | ||
let unsubscribe = this.__unsubscribeStore; | ||
unsubscribe && unsubscribe(); | ||
@@ -48,0 +77,0 @@ this.__unsubscribeStore = null; |
@@ -83,38 +83,40 @@ /** | ||
component: { | ||
methods: { | ||
/** | ||
* Watch the given expression or function | ||
* | ||
* @param {string|Function} expressOrFunc the expression or functon to watch | ||
* @param {Function|Object} callback the callback to execute when the | ||
* expression or function value changes | ||
* @param {Object=} options watch options | ||
* @param {boolean=} options.immediate whether trigger the callback | ||
* immediately with the current value of the expression or function | ||
* optional, by default false | ||
* @param {boolean=} optional.deep whether watch object nested value | ||
* optional, by default false | ||
* @return {Function} the unwatch api | ||
*/ | ||
$watch(expressOrFunc, callback, options) { | ||
let watcher = normalizeWatchItem.call( | ||
this, expressOrFunc, | ||
Object.assign({ | ||
handler: callback | ||
}, options) | ||
); | ||
return this.__computedObserver.addWatchComputed(watcher); | ||
}, | ||
/** | ||
* Watch the given expression or function | ||
* | ||
* @param {string|Function} expressOrFunc the expression or functon to watch | ||
* @param {Function|Object} callback the callback to execute when the | ||
* expression or function value changes | ||
* @param {Object=} options watch options | ||
* @param {boolean=} options.immediate whether trigger the callback | ||
* immediately with the current value of the expression or function | ||
* optional, by default false | ||
* @param {boolean=} optional.deep whether watch object nested value | ||
* optional, by default false | ||
* @return {Function} the unwatch api | ||
*/ | ||
$watch(expressOrFunc, callback, options) { | ||
let watcher = normalizeWatchItem.call( | ||
this, expressOrFunc, | ||
Object.assign({ | ||
handler: callback | ||
}, options) | ||
); | ||
return this.__computedObserver.addWatchComputed(watcher); | ||
}, | ||
/** | ||
* Call after observer inited | ||
* | ||
* @private | ||
*/ | ||
afterObserverInit() { | ||
this.__computedObserver.addWatchComputed( | ||
normalizeWatch.call(this, this.watch) | ||
); | ||
/** | ||
* Call after observer inited | ||
* | ||
* @private | ||
*/ | ||
afterObserverInit() { | ||
this.__computedObserver.addWatchComputed( | ||
normalizeWatch.call(this, this.watch) | ||
); | ||
} | ||
} | ||
} | ||
}; |
@@ -8,28 +8,20 @@ /** | ||
function formatProps(props) { | ||
if (Array.isArray(props)) { | ||
return props.map(key => ({[key]: {type: null}})); | ||
} | ||
import {normalizeProps} from './props'; | ||
let result = {}; | ||
Object.keys(props).forEach(k => { | ||
let {type, observer, default: value} = props[k]; | ||
if (typeof value === 'function') { | ||
value = value(); | ||
} | ||
/** | ||
* The lifecycle methods and properties added in okam | ||
* | ||
* @type {Array.<string>} | ||
*/ | ||
const extendPropMethods = [ | ||
'beforeCreate', 'beforeMount', 'mounted', | ||
'beforeDestroy', 'destroyed', 'updated', | ||
'computed' | ||
]; | ||
result[k] = { | ||
type, | ||
value, | ||
observer | ||
}; | ||
}); | ||
return result; | ||
} | ||
export function normalizeComponent(componentInfo) { | ||
let {props, properties, mixins, behaviors} = componentInfo; | ||
let {methods = {}, props, properties, mixins, behaviors} = componentInfo; | ||
if (!properties && props) { | ||
componentInfo.props = componentInfo.properties = formatProps(props); | ||
componentInfo.properties = normalizeProps(props); | ||
} | ||
@@ -41,3 +33,15 @@ | ||
// move new added methods and properties to methods object | ||
extendPropMethods.forEach(k => { | ||
let value = componentInfo[k]; | ||
if (typeof value === 'function') { | ||
methods[k] = value; | ||
} | ||
else if (value) { | ||
// convert non-method prop to method | ||
methods[k] = () => value; | ||
} | ||
}); | ||
componentInfo.methods = methods; | ||
return componentInfo; | ||
} |
@@ -14,7 +14,6 @@ /** | ||
import {mixin, isFunction} from '../util/index'; | ||
import {normalizePage} from './page'; | ||
import {normalizeComponent} from './component'; | ||
const usedExtensions = {}; | ||
const installedPlugins = []; | ||
const baseClasses = {}; | ||
@@ -26,8 +25,14 @@ const APP_TYPE = 'app'; | ||
function initExtensions(type, instance, base) { | ||
let plugins = usedExtensions[type]; | ||
let args = [instance]; | ||
plugins && Array.prototype.push.apply(args, plugins); | ||
args.push(base); | ||
let existedBase = baseClasses[type]; | ||
if (!existedBase) { | ||
let plugins = usedExtensions[type]; | ||
let args = [{}]; | ||
plugins && Array.prototype.push.apply(args, plugins); | ||
args.push(base); | ||
return mixin.apply(this, args); | ||
existedBase = mixin.apply(this, args); | ||
baseClasses[type] = existedBase; | ||
} | ||
return mixin.apply(this, [instance, existedBase]); | ||
} | ||
@@ -62,9 +67,3 @@ | ||
let {base, component, page, app} = plugin; | ||
if (base) { | ||
addExtension(APP_TYPE, base); | ||
addExtension(COMPONENT_TYPE, base); | ||
addExtension(PAGE_TYPE, base); | ||
} | ||
let {component, page, app} = plugin; | ||
if (component) { | ||
@@ -86,3 +85,3 @@ addExtension(COMPONENT_TYPE, component); | ||
export function createPage(instance, base, refs) { | ||
export function createPage(instance, base, normalize, refs) { | ||
refs && (instance.__refInfo = refs); | ||
@@ -92,3 +91,3 @@ let pageInfo = initExtensions(PAGE_TYPE, instance, base); | ||
initComponentData(pageInfo); | ||
normalizePage(pageInfo); | ||
normalize && (pageInfo = normalize(pageInfo)); | ||
@@ -98,3 +97,3 @@ return Page(pageInfo); | ||
export function createComponent(instance, base, refs) { | ||
export function createComponent(instance, base, normalize, refs) { | ||
refs && (instance.__refInfo = refs); | ||
@@ -104,5 +103,5 @@ let componentInfo = initExtensions(COMPONENT_TYPE, instance, base); | ||
initComponentData(componentInfo); | ||
normalizeComponent(componentInfo); | ||
normalize && (componentInfo = normalize(componentInfo)); | ||
return Component(componentInfo); | ||
} |
@@ -9,2 +9,3 @@ /** | ||
import {createPage} from './helper/factory'; | ||
import {normalizePage} from './helper/page'; | ||
import pageBase from './base/page'; | ||
@@ -16,4 +17,5 @@ | ||
pageBase, | ||
normalizePage, | ||
refComponents | ||
); | ||
} |
@@ -8,3 +8,4 @@ /** | ||
import 'regenerator-runtime/runtime'; | ||
import * as runtime from 'regenerator-runtime/runtime'; | ||
export default runtime; |
@@ -11,4 +11,10 @@ /** | ||
let currPromise; | ||
if (typeof Promise !== 'function') { | ||
global.Promise = PolyfillPromise; | ||
currPromise = global.Promise = PolyfillPromise; | ||
} | ||
else { | ||
currPromise = Promise; | ||
} | ||
export default currPromise; |
@@ -8,2 +8,3 @@ /** | ||
export * from '../App'; | ||
import App from '../App'; | ||
export default App; |
@@ -8,2 +8,3 @@ /** | ||
export * from '../Component'; | ||
import Component from '../Component'; | ||
export default Component; |
@@ -8,2 +8,3 @@ /** | ||
export * from '../Page'; | ||
import Page from '../Page'; | ||
export default Page; |
68810
39
2290
5