mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-17 05:30:33 +03:00
implement fix for #9 edge-case
This commit is contained in:
@@ -5,7 +5,7 @@ import Router from 'vue-router'
|
||||
Vue.use(Router)
|
||||
Vue.use(VueMeta)
|
||||
|
||||
const ChildComponent = () => ({
|
||||
const ChildComponent = {
|
||||
name: `child-component`,
|
||||
props: ['page'],
|
||||
template: `<h3>You're looking at the <strong>{{ page }}</strong> page</h3>`,
|
||||
@@ -14,13 +14,16 @@ const ChildComponent = () => ({
|
||||
return this.page
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// this wrapper function is not a requirement for vue-router,
|
||||
// just a demonstration that render-function style components also work.
|
||||
// See https://github.com/declandewet/vue-meta/issues/9 for more info.
|
||||
function view (page) {
|
||||
return {
|
||||
name: `section-${page}`,
|
||||
render (h) {
|
||||
return h(ChildComponent(), {
|
||||
return h(ChildComponent, {
|
||||
props: { page }
|
||||
})
|
||||
}
|
||||
|
||||
+1
-13
@@ -9,20 +9,8 @@ import generateServerInjector from './generateServerInjector'
|
||||
* @return {Object} - server meta info with `toString` methods
|
||||
*/
|
||||
export default function inject () {
|
||||
const Vue = this.constructor
|
||||
|
||||
// get meta info with sensible defaults
|
||||
const info = Vue.util.extend({
|
||||
title: '',
|
||||
htmlAttrs: {},
|
||||
bodyAttrs: {},
|
||||
meta: [],
|
||||
script: [],
|
||||
noscript: [],
|
||||
style: [],
|
||||
link: [],
|
||||
base: []
|
||||
}, getMetaInfo(this.$root))
|
||||
const info = getMetaInfo(this.$root)
|
||||
|
||||
// generate server injectors
|
||||
for (let key in info) {
|
||||
|
||||
@@ -23,12 +23,6 @@ export default function getComponentOption (opts, result = {}) {
|
||||
const data = $options[option]
|
||||
|
||||
if (typeof data === 'object') {
|
||||
// bind context of option methods (if any) to this component
|
||||
Object.keys(data).forEach((key) => {
|
||||
const value = data[key]
|
||||
data[key] = typeof value === 'function' ? value.bind(component) : value
|
||||
})
|
||||
|
||||
// merge with existing options
|
||||
result = deepmerge(result, data, {
|
||||
clone: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import deepmerge from 'deepmerge'
|
||||
import getComponentOption from './getComponentOption'
|
||||
import mergeComponentData from './mergeComponentData'
|
||||
|
||||
/**
|
||||
* Returns the correct meta info for the given component
|
||||
@@ -55,12 +56,6 @@ export default function getMetaInfo (component) {
|
||||
}
|
||||
})
|
||||
|
||||
// if any info options are a function, coerce them to the result of a call
|
||||
Object.keys(info).forEach((key) => {
|
||||
const val = info[key]
|
||||
info[key] = typeof val === 'function' && key !== 'changed' ? val() : val
|
||||
})
|
||||
|
||||
// backup the title chunk in case user wants access to it
|
||||
if (info.title) {
|
||||
info.titleChunk = info.title
|
||||
@@ -77,5 +72,16 @@ export default function getMetaInfo (component) {
|
||||
info.base = Object.keys(info.base).length ? [info.base] : []
|
||||
}
|
||||
|
||||
return deepmerge(defaultInfo, info)
|
||||
const metaInfo = deepmerge(defaultInfo, info)
|
||||
const componentData = mergeComponentData(component)
|
||||
|
||||
// inject component context into functions & call to normalize data
|
||||
Object.keys(metaInfo).forEach((key) => {
|
||||
const val = metaInfo[key]
|
||||
if (typeof val === 'function') {
|
||||
metaInfo[key] = val.call(componentData)
|
||||
}
|
||||
})
|
||||
|
||||
return metaInfo
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Recursively shallow-merges component object with it's children component objects.
|
||||
* This function is responsible for obtaining the `this` context of metaInfo props when
|
||||
* declared in function form.
|
||||
*
|
||||
* @param {Object} component - the component object
|
||||
* @return {Object} - the merged data
|
||||
*/
|
||||
export default function mergeComponentData (component) {
|
||||
if (component.$children.length) {
|
||||
return component.$children.reduce((data, child) => {
|
||||
return Object.assign({}, data, mergeComponentData(child))
|
||||
}, component)
|
||||
}
|
||||
return component
|
||||
}
|
||||
@@ -26,9 +26,10 @@ export default function VueMeta (Vue) {
|
||||
|
||||
requestId = window.requestAnimationFrame(() => {
|
||||
requestId = null
|
||||
const info = getMetaInfo(this.$root)
|
||||
|
||||
// update the meta info
|
||||
updateClientMetaInfo(getMetaInfo(this.$root))
|
||||
updateClientMetaInfo(info)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -19,21 +19,6 @@ describe('getComponentOption', () => {
|
||||
expect(fetchedOption).to.eql('foo')
|
||||
})
|
||||
|
||||
it('binds option method context to the component instance', () => {
|
||||
component = new Vue({
|
||||
data: {
|
||||
age: 44
|
||||
},
|
||||
foo: {
|
||||
bar () {
|
||||
return this.age
|
||||
}
|
||||
}
|
||||
})
|
||||
const fetchedOption = getComponentOption({ component, option: 'foo' })
|
||||
expect(fetchedOption.bar()).to.equal(44)
|
||||
})
|
||||
|
||||
it('fetches deeply nested component options and merges them', () => {
|
||||
Vue.component('merge-child', { template: '<div></div>', foo: { bar: 'baz' } })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user