hg-sid
Version:
a front-end simple framework with mvc
137 lines (121 loc) • 3.07 kB
text/typescript
import { empty, noop } from './util'
import { LIFECYCLE_HOOK } from '../instance/lifecycle'
// 规范并合并配置项
export function mergeOptions(parent: any = {}, child: any = {}) {
// 规范部分特殊属性
normalizeComputed(parent)
normalizeComputed(child)
normalizeProp(child)
// 直接合并 parent 和 child ,避免
// 除 data/methods/watch/computed/LIFECYCLE_HOOK 之外的属性丢失
let options = Object.assign({}, parent, child)
LIFECYCLE_HOOK.forEach(name => {
normalizeLifecycle(child, name)
normalizeLifecycle(parent, name)
options[name] = parent[name].concat(child[name])
})
// 合并 data ,一个函数
options.data = mergeData(parent.data, child.data)
// 合并 methods 同名覆盖
options.methods = Object.assign(parent.methods || {}, child.methods || {})
// 合并 watcher 同名合并成一个数组
options.watch = mergeWatch(parent.watch, child.watch)
// 合并 computed 同名覆盖
options.computed = Object.assign(parent.computed || {}, child.computed || {})
return options
}
function mergeData(parentVal: any = empty, childVal: any = empty) {
return function() {
// parentVal / childVal 是函数
return Object.assign(parentVal.call(this), childVal.call(this))
}
}
/**
* 规范 computed 结构
* @param option
* return {
* key: fn(val, oldVal)
* }
*/
function mergeWatch(parentVal: any = {}, childVal: any = {}) {
let ret = Object.assign({}, parentVal)
for (let key in childVal) {
let parent = ret[key]
let child = childVal[key]
if (parent && !Array.isArray(parent)) {
parent = [parent]
}
ret[key] = parent
? parent.concat(child)
: Array.isArray(child)
? child
: [child]
}
return ret
}
/**
* 规范 computed 结构
* @param option
* return {
* key: {
* get: Function,
* set: Function
* }
* }
*/
export function normalizeComputed(option: any) {
let computed = option.computed
for (let key in computed) {
// 支持 option.computed[key] 为函数
if (typeof computed[key] === 'function') {
option.computed[key] = {
get: computed[key],
set: noop
}
}
}
}
/**
* 规范 prop 结构
* @param option
* return {
* key: {
* type: String|Number|...,
* ...
* }
* }
*/
export function normalizeProp(option: any) {
if (!option.props) return
let props = option.props
let normalProps: any = {}
// 支持 props 为数组
if (Array.isArray(props)) {
props.forEach(item => {
normalProps[item] = {
type: null
}
})
} else {
for (let key in props) {
normalProps[key] = Object.assign({ type: null }, props[key])
}
}
option.props = normalProps
}
/**
* 规范 生命周期 结构
* @param option
* return {
* LIFECYCLE_HOOK_name: [fn]
* }
*/
export function normalizeLifecycle(option: any, name: string) {
if (option[name] === undefined) {
option[name] = []
return
}
if (!Array.isArray(option[name])) {
option[name] = [option[name]]
}
}