UNPKG

silk-gui

Version:

GUI for developers and Node OS

258 lines (236 loc) 5.64 kB
var _ = require('./index') var extend = _.extend /** * Option overwriting strategies are functions that handle * how to merge a parent option value and a child option * value into the final value. * * All strategy functions follow the same signature: * * @param {*} parentVal * @param {*} childVal * @param {Vue} [vm] */ var strats = Object.create(null) /** * Helper that recursively merges two data objects together. */ function mergeData (to, from) { var key, toVal, fromVal for (key in from) { toVal = to[key] fromVal = from[key] if (!to.hasOwnProperty(key)) { to.$add(key, fromVal) } else if (_.isObject(toVal) && _.isObject(fromVal)) { mergeData(toVal, fromVal) } } return to } /** * Data */ strats.data = function (parentVal, childVal, vm) { if (!vm) { // in a Vue.extend merge, both should be functions if (!childVal) { return parentVal } if (typeof childVal !== 'function') { _.warn( 'The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.' ) return parentVal } if (!parentVal) { return childVal } // when parentVal & childVal are both present, // we need to return a function that returns the // merged result of both functions... no need to // check if parentVal is a function here because // it has to be a function to pass previous merges. return function mergedDataFn () { return mergeData( childVal.call(this), parentVal.call(this) ) } } else { // instance merge, return raw object var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined if (instanceData) { return mergeData(instanceData, defaultData) } else { return defaultData } } } /** * El */ strats.el = function (parentVal, childVal, vm) { if (!vm && childVal && typeof childVal !== 'function') { _.warn( 'The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.' ) return } var ret = childVal || parentVal // invoke the element factory if this is instance merge return vm && typeof ret === 'function' ? ret.call(vm) : ret } /** * Hooks and param attributes are merged as arrays. */ strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.paramAttributes = function (parentVal, childVal) { return childVal ? parentVal ? parentVal.concat(childVal) : _.isArray(childVal) ? childVal : [childVal] : parentVal } /** * Assets * * When a vm is present (instance creation), we need to do * a three-way merge between constructor options, instance * options and parent options. */ strats.directives = strats.filters = strats.partials = strats.transitions = strats.components = function (parentVal, childVal, vm, key) { var ret = Object.create( vm && vm.$parent ? vm.$parent.$options[key] : _.Vue.options[key] ) if (parentVal) { var keys = Object.keys(parentVal) var i = keys.length var field while (i--) { field = keys[i] ret[field] = parentVal[field] } } if (childVal) extend(ret, childVal) return ret } /** * Events & Watchers. * * Events & watchers hashes should not overwrite one * another, so we merge them as arrays. */ strats.watch = strats.events = function (parentVal, childVal) { if (!childVal) return parentVal if (!parentVal) return childVal var ret = {} extend(ret, parentVal) for (var key in childVal) { var parent = ret[key] var child = childVal[key] if (parent && !_.isArray(parent)) { parent = [parent] } ret[key] = parent ? parent.concat(child) : [child] } return ret } /** * Other object hashes. */ strats.methods = strats.computed = function (parentVal, childVal) { if (!childVal) return parentVal if (!parentVal) return childVal var ret = Object.create(parentVal) extend(ret, childVal) return ret } /** * Default strategy. */ var defaultStrat = function (parentVal, childVal) { return childVal === undefined ? parentVal : childVal } /** * Make sure component options get converted to actual * constructors. * * @param {Object} components */ function guardComponents (components) { if (components) { var def for (var key in components) { def = components[key] if (_.isPlainObject(def)) { def.name = key components[key] = _.Vue.extend(def) } } } } /** * Merge two option objects into a new one. * Core utility used in both instantiation and inheritance. * * @param {Object} parent * @param {Object} child * @param {Vue} [vm] - if vm is present, indicates this is * an instantiation merge. */ module.exports = function mergeOptions (parent, child, vm) { guardComponents(child.components) var options = {} var key if (child.mixins) { for (var i = 0, l = child.mixins.length; i < l; i++) { parent = mergeOptions(parent, child.mixins[i], vm) } } for (key in parent) { merge(key) } for (key in child) { if (!(parent.hasOwnProperty(key))) { merge(key) } } function merge (key) { var strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key) } return options }