2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-25 01:20:34 +03:00

refactor: optimize getComponentOption by making it less generic

This commit is contained in:
pimlie
2019-03-08 13:40:30 +01:00
committed by Alexander Lichter
parent 7b888c9437
commit 23c3380c90
3 changed files with 62 additions and 61 deletions
+37 -36
View File
@@ -1,7 +1,7 @@
import deepmerge from 'deepmerge' import { merge } from './merge'
import uniqueId from 'lodash.uniqueid' import applyTemplate from './applyTemplate'
import { isUndefined, isFunction, isObject } from './typeof' import inMetaInfoBranch from './inMetaInfoBranch'
import uniqBy from './uniqBy' import { isFunction, isObject } from './typeof'
/** /**
* Returns the `opts.option` $option value of the given `opts.component`. * Returns the `opts.option` $option value of the given `opts.component`.
@@ -17,15 +17,16 @@ import uniqBy from './uniqBy'
* @param {Object} [result={}] - result so far * @param {Object} [result={}] - result so far
* @return {Object} result - final aggregated result * @return {Object} result - final aggregated result
*/ */
export default function getComponentOption({ component, deep, arrayMerge, keyName, metaTemplateKeyName, tagIDKeyName, contentKeyName } = {}, result = {}) { export default function getComponentOption(options = {}, result = {}) {
const { $options } = component const { component, keyName, metaTemplateKeyName, tagIDKeyName } = options
const { $options, $children } = component
if (component._inactive) { if (component._inactive) {
return result return result
} }
// only collect option data if it exists // only collect option data if it exists
if (!isUndefined($options[keyName]) && $options[keyName] !== null) { if ($options[keyName]) {
let data = $options[keyName] let data = $options[keyName]
// if option is a function, replace it with it's result // if option is a function, replace it with it's result
@@ -33,46 +34,46 @@ export default function getComponentOption({ component, deep, arrayMerge, keyNam
data = data.call(component) data = data.call(component)
} }
if (isObject(data)) { // ignore data if its not an object, then we keep our previous result
// merge with existing options if (!isObject(data)) {
result = deepmerge(result, data, { arrayMerge }) console.log(data)
} else { return result
result = data
} }
// merge with existing options
result = merge(result, data, options)
} }
// collect & aggregate child options if deep = true // collect & aggregate child options if deep = true
if (deep && component.$children.length) { if ($children.length) {
component.$children.forEach((childComponent) => { $children.forEach((childComponent) => {
// check if the childComponent is in a branch
// return otherwise so we dont walk all component branches unnecessarily
if (!inMetaInfoBranch(childComponent)) {
return
}
result = getComponentOption({ result = getComponentOption({
component: childComponent, ...options,
keyName, component: childComponent
deep,
arrayMerge
}, result) }, result)
}) })
} }
if (metaTemplateKeyName && result.hasOwnProperty('meta')) { if (metaTemplateKeyName && result.meta) {
result.meta = Object.keys(result.meta).map((metaKey) => { // apply templates if needed
const metaObject = result.meta[metaKey] result.meta.forEach(metaObject => applyTemplate(options, metaObject))
if (!metaObject.hasOwnProperty(metaTemplateKeyName) || !metaObject.hasOwnProperty(contentKeyName) || isUndefined(metaObject[metaTemplateKeyName])) {
return result.meta[metaKey]
}
const template = metaObject[metaTemplateKeyName] // remove meta items with duplicate vmid's
delete metaObject[metaTemplateKeyName] result.meta = result.meta.filter((metaItem, index, arr) => {
return (
if (template) { // keep meta item if it doesnt has a vmid
metaObject.content = isFunction(template) ? template(metaObject.content) : template.replace(/%s/g, metaObject.content) !metaItem.hasOwnProperty(tagIDKeyName) ||
} // or if it's the first item in the array with this vmid
index === arr.findIndex(item => item[tagIDKeyName] === metaItem[tagIDKeyName])
return metaObject )
}) })
result.meta = uniqBy(
result.meta,
metaObject => metaObject.hasOwnProperty(tagIDKeyName) ? metaObject[tagIDKeyName] : uniqueId()
)
} }
return result return result
} }
-7
View File
@@ -1,7 +0,0 @@
export default function uniqBy(inputArray, predicate) {
return inputArray
.filter((x, i, arr) => i === arr.length - 1
? true
: predicate(x) !== predicate(arr[i + 1])
)
}
+25 -18
View File
@@ -1,5 +1,5 @@
import getComponentOption from '../src/shared/getComponentOption' import getComponentOption from '../src/shared/getComponentOption'
import { getVue } from './utils' import { mount, getVue, loadVueMetaPlugin } from './utils'
describe('getComponentOption', () => { describe('getComponentOption', () => {
let Vue let Vue
@@ -31,46 +31,53 @@ describe('getComponentOption', () => {
}) })
it('fetches deeply nested component options and merges them', () => { it('fetches deeply nested component options and merges them', () => {
Vue.component('merge-child', { render: h => h('div'), foo: { bar: 'baz' } }) const localVue = loadVueMetaPlugin(true, { keyName: 'foo' })
localVue.component('merge-child', { render: h => h('div'), foo: { bar: 'baz' } })
const component = new Vue({ const component = localVue.component('parent', {
foo: { fizz: 'buzz' }, foo: { fizz: 'buzz' },
el: document.createElement('div'),
render: h => h('div', null, [h('merge-child')]) render: h => h('div', null, [h('merge-child')])
}) })
const mergedOption = getComponentOption({ component, keyName: 'foo', deep: true }) const wrapper = mount(component, { localVue })
const mergedOption = getComponentOption({ component: wrapper.vm, keyName: 'foo' })
expect(mergedOption).toEqual({ bar: 'baz', fizz: 'buzz' }) expect(mergedOption).toEqual({ bar: 'baz', fizz: 'buzz' })
}) })
it('allows for a custom array merge strategy', () => { it('allows for a custom array merge strategy', () => {
Vue.component('array-child', { const localVue = loadVueMetaPlugin(false, { keyName: 'foo' })
localVue.component('array-child', {
render: h => h('div'), render: h => h('div'),
foo: [ foo: {
{ name: 'flower', content: 'rose' } meta: [
] { name: 'flower', content: 'rose' }
]
}
}) })
const component = new Vue({ const component = localVue.component('parent', {
foo: [ foo: {
{ name: 'flower', content: 'tulip' } meta: [
], { name: 'flower', content: 'tulip' }
el: document.createElement('div'), ]
},
render: h => h('div', null, [h('array-child')]) render: h => h('div', null, [h('array-child')])
}) })
const wrapper = mount(component, { localVue })
const mergedOption = getComponentOption({ const mergedOption = getComponentOption({
component, component: wrapper.vm,
keyName: 'foo', keyName: 'foo',
deep: true,
arrayMerge(target, source) { arrayMerge(target, source) {
return target.concat(source) return target.concat(source)
} }
}) })
expect(mergedOption).toEqual([ expect(mergedOption).toEqual({ meta: [
{ name: 'flower', content: 'tulip' }, { name: 'flower', content: 'tulip' },
{ name: 'flower', content: 'rose' } { name: 'flower', content: 'rose' }
]) ] })
}) })
}) })