mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-22 05:50:33 +03:00
support for client tag updates
This commit is contained in:
@@ -1,10 +1,23 @@
|
|||||||
import updateTitle from './updaters/updateTitle'
|
import updateTitle from './updaters/updateTitle'
|
||||||
import updateTagAttributes from './updaters/updateTagAttributes'
|
import updateTagAttributes from './updaters/updateTagAttributes'
|
||||||
|
import updateTags from './updaters/updateTags'
|
||||||
import { SERVER_RENDERED_ATTRIBUTE } from '../shared/constants'
|
import { SERVER_RENDERED_ATTRIBUTE } from '../shared/constants'
|
||||||
|
|
||||||
|
// tags to watch
|
||||||
|
const tags = [
|
||||||
|
'meta',
|
||||||
|
'link',
|
||||||
|
'base',
|
||||||
|
'style',
|
||||||
|
'script',
|
||||||
|
'noscript'
|
||||||
|
]
|
||||||
|
|
||||||
|
// hoisted vars but only in the browser
|
||||||
if (typeof window !== 'undefined' && window !== null) {
|
if (typeof window !== 'undefined' && window !== null) {
|
||||||
var htmlTag = document.getElementsByTagName('html')[0]
|
var htmlTag = document.getElementsByTagName('html')[0]
|
||||||
var bodyTag = document.getElementsByTagName('body')[0]
|
var bodyTag = document.getElementsByTagName('body')[0]
|
||||||
|
var headTag = document.getElementsByTagName('head')[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,6 +36,14 @@ export default function updateClientMetaInfo (newInfo, $root) {
|
|||||||
|
|
||||||
// update <body> attrs
|
// update <body> attrs
|
||||||
updateTagAttributes(newInfo.bodyAttrs, bodyTag)
|
updateTagAttributes(newInfo.bodyAttrs, bodyTag)
|
||||||
|
|
||||||
|
// update tags
|
||||||
|
for (let i = 0, len = tags.length; i < len; i++) {
|
||||||
|
const tag = tags[i]
|
||||||
|
if (newInfo[tag]) {
|
||||||
|
updateTags(tag, newInfo[tag], headTag)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
htmlTag.removeAttribute(SERVER_RENDERED_ATTRIBUTE)
|
htmlTag.removeAttribute(SERVER_RENDERED_ATTRIBUTE)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { VUE_META_ATTRIBUTE } from '../../shared/constants'
|
||||||
|
|
||||||
|
// borrow the slice method
|
||||||
|
const toArray = Function.prototype.call.bind(Array.prototype.slice)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates meta tags inside <head> on the client. Borrowed from `react-helmet`:
|
||||||
|
* https://github.com/nfl/react-helmet/blob/004d448f8de5f823d10f838b02317521180f34da/src/Helmet.js#L195-L245
|
||||||
|
*
|
||||||
|
* @param {('meta'|'base'|'link'|'style'|'script'|'noscript')} type - the name of the tag
|
||||||
|
* @param {(Array<Object>|Object)} tags - an array of tag objects or a single object in case of base
|
||||||
|
* @return {Object} - a representation of what tags changed
|
||||||
|
*/
|
||||||
|
export default function updateTags (type, tags, headTag) {
|
||||||
|
const nodes = headTag.querySelectorAll(`${type}[${VUE_META_ATTRIBUTE}]`)
|
||||||
|
const oldTags = toArray(nodes)
|
||||||
|
const newTags = []
|
||||||
|
let indexToDelete
|
||||||
|
|
||||||
|
if (tags && tags.length) {
|
||||||
|
tags.forEach((tag) => {
|
||||||
|
const newElement = document.createElement(type)
|
||||||
|
|
||||||
|
for (const attribute in tag) {
|
||||||
|
if (tag.hasOwnProperty(attribute)) {
|
||||||
|
if (attribute === 'innerHTML') {
|
||||||
|
newElement.innerHTML = tag.innerHTML
|
||||||
|
} else if (attribute === 'cssText') {
|
||||||
|
if (newElement.styleSheet) {
|
||||||
|
newElement.styleSheet.cssText = tag.cssText
|
||||||
|
} else {
|
||||||
|
newElement.appendChild(document.createTextNode(tag.cssText))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const value = (typeof tag[attribute] === 'undefined') ? '' : tag[attribute]
|
||||||
|
newElement.setAttribute(attribute, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newElement.setAttribute(VUE_META_ATTRIBUTE, 'true')
|
||||||
|
|
||||||
|
// Remove a duplicate tag from domTagstoRemove, so it isn't cleared.
|
||||||
|
if (oldTags.some((existingTag, index) => {
|
||||||
|
indexToDelete = index
|
||||||
|
return newElement.isEqualNode(existingTag)
|
||||||
|
})) {
|
||||||
|
oldTags.splice(indexToDelete, 1)
|
||||||
|
} else {
|
||||||
|
newTags.push(newElement)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
oldTags.forEach((tag) => tag.parentNode.removeChild(tag))
|
||||||
|
newTags.forEach((tag) => headTag.appendChild(tag))
|
||||||
|
|
||||||
|
return { oldTags, newTags }
|
||||||
|
}
|
||||||
@@ -10,11 +10,6 @@ import { VUE_META_ATTRIBUTE } from '../../shared/constants'
|
|||||||
export default function tagGenerator (type, tags) {
|
export default function tagGenerator (type, tags) {
|
||||||
return {
|
return {
|
||||||
text () {
|
text () {
|
||||||
// there can only be one `base` tag on a page, so we give it special treatment
|
|
||||||
if (type === 'base') {
|
|
||||||
tags = Object.keys(tags).length ? [tags] : []
|
|
||||||
}
|
|
||||||
|
|
||||||
// build a string containing all tags of this type
|
// build a string containing all tags of this type
|
||||||
return tags.reduce((tagsStr, tag) => {
|
return tags.reduce((tagsStr, tag) => {
|
||||||
// build a string containing all attributes of this tag
|
// build a string containing all attributes of this tag
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function inject () {
|
|||||||
noscript: [],
|
noscript: [],
|
||||||
style: [],
|
style: [],
|
||||||
link: [],
|
link: [],
|
||||||
base: {}
|
base: []
|
||||||
}, getMetaInfo(this.$root))
|
}, getMetaInfo(this.$root))
|
||||||
|
|
||||||
// generate server injectors
|
// generate server injectors
|
||||||
|
|||||||
@@ -31,5 +31,10 @@ export default function getMetaInfo (component) {
|
|||||||
info.title = info.titleTemplate.replace(/%s/g, info.titleChunk)
|
info.title = info.titleTemplate.replace(/%s/g, info.titleChunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert base tag to an array
|
||||||
|
if (info.base) {
|
||||||
|
info.base = Object.keys(info.base).length ? [info.base] : []
|
||||||
|
}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user