mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-21 18:50:34 +03:00
feat: add option waitOnDestroyed
This commit is contained in:
+7
-2
@@ -20,17 +20,22 @@ export default function $meta (options) {
|
||||
'setOptions': (newOptions) => {
|
||||
const refreshNavKey = 'refreshOnceOnNavigation'
|
||||
if (newOptions && newOptions[refreshNavKey]) {
|
||||
options.refreshOnceOnNavigation = newOptions[refreshNavKey]
|
||||
options.refreshOnceOnNavigation = !!newOptions[refreshNavKey]
|
||||
addNavGuards($root)
|
||||
}
|
||||
|
||||
const debounceWaitKey = 'debounceWait'
|
||||
if (newOptions && newOptions[debounceWaitKey]) {
|
||||
if (newOptions && debounceWaitKey in newOptions) {
|
||||
const debounceWait = parseInt(newOptions[debounceWaitKey])
|
||||
if (!isNaN(debounceWait)) {
|
||||
options.debounceWait = debounceWait
|
||||
}
|
||||
}
|
||||
|
||||
const waitOnDestroyedKey = 'waitOnDestroyed'
|
||||
if (newOptions && waitOnDestroyedKey in newOptions) {
|
||||
options.waitOnDestroyed = !!newOptions[waitOnDestroyedKey]
|
||||
}
|
||||
},
|
||||
'refresh': () => refresh($root, options),
|
||||
'inject': () => process.server ? inject($root, options) : showWarningNotSupportedInBrowserBundle('inject'),
|
||||
|
||||
@@ -52,6 +52,9 @@ export const ssrAppId = 'ssr'
|
||||
// How long meta update
|
||||
export const debounceWait = 10
|
||||
|
||||
// How long meta update
|
||||
export const waitOnDestroyed = true
|
||||
|
||||
export const defaultOptions = {
|
||||
keyName,
|
||||
attribute,
|
||||
@@ -59,6 +62,7 @@ export const defaultOptions = {
|
||||
tagIDKeyName,
|
||||
contentKeyName,
|
||||
metaTemplateKeyName,
|
||||
waitOnDestroyed,
|
||||
debounceWait,
|
||||
ssrAppId
|
||||
}
|
||||
|
||||
+16
-9
@@ -147,25 +147,32 @@ export default function createMixin (Vue, options) {
|
||||
},
|
||||
// TODO: move back into beforeCreate when Vue issue is resolved
|
||||
destroyed () {
|
||||
const $this = this
|
||||
// do not trigger refresh:
|
||||
// - when user configured to not wait for transitions on destroyed
|
||||
// - when the component doesnt have a parent
|
||||
// - doesnt have metaInfo defined
|
||||
if (!$this.$parent || !hasMetaInfo($this)) {
|
||||
if (!this.$parent || !hasMetaInfo(this)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Wait that element is hidden before refreshing meta tags (to support animations)
|
||||
const interval = setInterval(() => {
|
||||
if ($this.$el && $this.$el.offsetParent !== null) {
|
||||
/* istanbul ignore next line */
|
||||
this.$nextTick(() => {
|
||||
if (!options.waitOnDestroyed || !this.$el || !this.$el.offsetParent) {
|
||||
triggerUpdate(options, this.$root, 'destroyed')
|
||||
return
|
||||
}
|
||||
|
||||
clearInterval(interval)
|
||||
// Wait that element is hidden before refreshing meta tags (to support animations)
|
||||
const interval = setInterval(() => {
|
||||
if (this.$el && this.$el.offsetParent !== null) {
|
||||
/* istanbul ignore next line */
|
||||
return
|
||||
}
|
||||
|
||||
triggerUpdate(options, $this.$root, 'destroyed')
|
||||
}, 50)
|
||||
clearInterval(interval)
|
||||
|
||||
triggerUpdate(options, this.$root, 'destroyed')
|
||||
}, 50)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isObject } from '../utils/is-type'
|
||||
import { isObject, isUndefined } from '../utils/is-type'
|
||||
import { defaultOptions } from './constants'
|
||||
|
||||
export function setOptions (options) {
|
||||
@@ -17,7 +17,8 @@ export function setOptions (options) {
|
||||
tagIDKeyName: options['tagIDKeyName'] || defaultOptions.tagIDKeyName,
|
||||
contentKeyName: options['contentKeyName'] || defaultOptions.contentKeyName,
|
||||
metaTemplateKeyName: options['metaTemplateKeyName'] || defaultOptions.metaTemplateKeyName,
|
||||
debounceWait: options['debounceWait'] || defaultOptions.debounceWait,
|
||||
debounceWait: isUndefined(options['debounceWait']) ? defaultOptions.debounceWait : options['debounceWait'],
|
||||
waitOnDestroyed: isUndefined(options['waitOnDestroyed']) ? defaultOptions.waitOnDestroyed : options['waitOnDestroyed'],
|
||||
ssrAppId: options['ssrAppId'] || defaultOptions.ssrAppId,
|
||||
refreshOnceOnNavigation: !!options['refreshOnceOnNavigation']
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getComponentMetaInfo } from '../../src/shared/getComponentOption'
|
||||
import _getMetaInfo from '../../src/shared/getMetaInfo'
|
||||
import { triggerUpdate, batchUpdate } from '../../src/client/update'
|
||||
import { mount, createWrapper, loadVueMetaPlugin, vmTick, clearClientAttributeMap } from '../utils'
|
||||
import { defaultOptions } from '../../src/shared/constants'
|
||||
|
||||
@@ -10,6 +11,7 @@ import Changed from '../components/changed.vue'
|
||||
|
||||
const getMetaInfo = component => _getMetaInfo(defaultOptions, getComponentMetaInfo(defaultOptions, component))
|
||||
|
||||
jest.mock('../../src/client/update')
|
||||
jest.mock('../../src/utils/window', () => ({
|
||||
hasGlobalWindow: false
|
||||
}))
|
||||
@@ -48,6 +50,8 @@ describe('components', () => {
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
elements.html.getAttributeNames().forEach(name => elements.html.removeAttribute(name))
|
||||
elements.head.childNodes.forEach(child => child.remove())
|
||||
elements.head.getAttributeNames().forEach(name => elements.head.removeAttribute(name))
|
||||
@@ -209,6 +213,10 @@ describe('components', () => {
|
||||
})
|
||||
|
||||
test('changed function is called', async () => {
|
||||
const update = jest.requireActual('../../src/client/update')
|
||||
triggerUpdate.mockImplementation(update.triggerUpdate)
|
||||
batchUpdate.mockImplementation(update.batchUpdate)
|
||||
|
||||
let context
|
||||
const changed = jest.fn(function () {
|
||||
context = this
|
||||
@@ -226,6 +234,9 @@ describe('components', () => {
|
||||
|
||||
expect(changed).toHaveBeenCalledTimes(2)
|
||||
expect(context._uid).toBe(wrapper.vm._uid)
|
||||
|
||||
triggerUpdate.mockRestore()
|
||||
batchUpdate.mockRestore()
|
||||
})
|
||||
|
||||
test('afterNavigation function is called with refreshOnce: true', async () => {
|
||||
@@ -299,6 +310,10 @@ describe('components', () => {
|
||||
})
|
||||
|
||||
test('changes before hydration initialization trigger an update', async () => {
|
||||
const update = jest.requireActual('../../src/client/update')
|
||||
triggerUpdate.mockImplementation(update.triggerUpdate)
|
||||
batchUpdate.mockImplementation(update.batchUpdate)
|
||||
|
||||
const { html } = elements
|
||||
html.setAttribute(defaultOptions.ssrAttribute, 'true')
|
||||
|
||||
@@ -342,9 +357,16 @@ describe('components', () => {
|
||||
|
||||
expect(html.getAttribute('theme')).toBe('dark')
|
||||
wrapper.destroy()
|
||||
|
||||
triggerUpdate.mockRestore()
|
||||
batchUpdate.mockRestore()
|
||||
})
|
||||
|
||||
test('changes during hydration initialization trigger an update', async () => {
|
||||
const update = jest.requireActual('../../src/client/update')
|
||||
triggerUpdate.mockImplementation(update.triggerUpdate)
|
||||
batchUpdate.mockImplementation(update.batchUpdate)
|
||||
|
||||
const { html } = elements
|
||||
html.setAttribute(defaultOptions.ssrAttribute, 'true')
|
||||
|
||||
@@ -386,6 +408,9 @@ describe('components', () => {
|
||||
|
||||
expect(html.getAttribute('theme')).toBe('dark')
|
||||
wrapper.destroy()
|
||||
|
||||
triggerUpdate.mockRestore()
|
||||
batchUpdate.mockRestore()
|
||||
})
|
||||
|
||||
test('can add/remove meta info from additional app ', () => {
|
||||
@@ -504,13 +529,34 @@ describe('components', () => {
|
||||
expect(guards.after).not.toBeUndefined()
|
||||
})
|
||||
|
||||
test('can set option debounceWait runtime', () => {
|
||||
const wrapper = mount(HelloWorld, { localVue: Vue })
|
||||
test('destroyed hook calls triggerUpdate delayed', async () => {
|
||||
jest.useFakeTimers()
|
||||
const wrapper = mount(HelloWorld, { localVue: Vue, parentComponent: { render: h => h('div') } })
|
||||
const spy = jest.spyOn(wrapper.vm.$el, 'offsetParent', 'get').mockReturnValue(true)
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().debounceWait).toBe(10)
|
||||
wrapper.destroy()
|
||||
|
||||
wrapper.vm.$meta().setOptions({ debounceWait: 69420 })
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().debounceWait).toBe(69420)
|
||||
expect(triggerUpdate).toHaveBeenCalledTimes(1)
|
||||
spy.mockRestore()
|
||||
|
||||
jest.advanceTimersByTime(51)
|
||||
|
||||
expect(triggerUpdate).toHaveBeenCalledTimes(2)
|
||||
expect(triggerUpdate).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), 'destroyed')
|
||||
})
|
||||
|
||||
test('destroyed hook calls triggerUpdate immediately when waitOnDestroyed: false', async () => {
|
||||
jest.useFakeTimers()
|
||||
|
||||
const wrapper = mount(HelloWorld, { localVue: Vue, parentComponent: { render: h => h('div') } })
|
||||
wrapper.vm.$meta().setOptions({ waitOnDestroyed: false })
|
||||
wrapper.destroy()
|
||||
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(triggerUpdate).toHaveBeenCalledTimes(2)
|
||||
expect(triggerUpdate).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), 'destroyed')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -61,7 +61,7 @@ describe('generators', () => {
|
||||
}
|
||||
})
|
||||
|
||||
describe.only('extra tests', () => {
|
||||
describe('extra tests', () => {
|
||||
test('empty config doesnt generate a tag', () => {
|
||||
const { meta } = generateServerInjector({ meta: [] })
|
||||
|
||||
|
||||
@@ -263,4 +263,24 @@ describe('plugin', () => {
|
||||
jest.advanceTimersByTime(10)
|
||||
expect(refreshSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('can set option waitOnDestroyed runtime', () => {
|
||||
const wrapper = mount({ render: h => h('div') }, { localVue: Vue })
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().waitOnDestroyed).toBe(true)
|
||||
|
||||
wrapper.vm.$meta().setOptions({ waitOnDestroyed: false })
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().waitOnDestroyed).toBe(false)
|
||||
})
|
||||
|
||||
test('can set option debounceWait runtime', () => {
|
||||
const wrapper = mount({ render: h => h('div') }, { localVue: Vue })
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().debounceWait).toBe(10)
|
||||
|
||||
wrapper.vm.$meta().setOptions({ debounceWait: 69420 })
|
||||
|
||||
expect(wrapper.vm.$meta().getOptions().debounceWait).toBe(69420)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user