From 97badf61cbdf4505ffc284cd3cd60e565fbc26c4 Mon Sep 17 00:00:00 2001 From: pimlie Date: Tue, 5 Mar 2019 15:11:25 +0100 Subject: [PATCH] feat: add afterNavigation callback (fix: #259) --- README.md | 18 ++++++++++++++++++ examples/vue-router/app.js | 14 +++++++++++--- src/client/refresh.js | 2 +- src/shared/mixin.js | 7 ++++++- src/shared/options.js | 12 +++++++++++- test/plugin-browser.test.js | 2 +- 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5cc9165..3ef4140 100644 --- a/README.md +++ b/README.md @@ -657,6 +657,24 @@ Will be called when the client `metaInfo` updates/changes. Receives the followin Default `false`. If set to `true` then vue-meta will pause updating `metaInfo` during page navigation and only refresh once when navigation has finished. It does this by adding a global beforeEach and afterEach navigation guard on the vue-router instance. +#### `afterNavigation` (Function) + +Will be called when the client `metaInfo` has changed after navigation occured. Receives the following parameters: +- `newInfo` (Object) - The new state of the `metaInfo` object. + +> :warning: This option only works when `refreshOnceOnNavigation: true`. Please see the [vue-router example](./examples/vue-router) + +`this` context is the component instance `afterNavigation` is defined on. + +```js +{ + metaInfo: { + afterNavigation (newInfo) { + console.log('Meta info update finished after navigation!') + } + } +} +``` ### How `metaInfo` is Resolved diff --git a/examples/vue-router/app.js b/examples/vue-router/app.js index 5057042..d46b3c8 100644 --- a/examples/vue-router/app.js +++ b/examples/vue-router/app.js @@ -7,18 +7,26 @@ Vue.use(VueMeta, { refreshOnceOnNavigation: true }) +let metaUpdated = 'no' const ChildComponent = { name: `child-component`, props: ['page'], - template: `

You're looking at the {{ page }} page

`, + template: `
+

You're looking at the {{ page }} page

+

Has metaInfo been updated? {{ metaUpdated }}

+
`, metaInfo () { return { - title: `${this.page} - ${this.date && this.date.toTimeString()}` + title: `${this.page} - ${this.date && this.date.toTimeString()}`, + afterNavigation() { + metaUpdated = 'yes' + } } }, data() { return { - date: null + date: null, + metaUpdated }; }, mounted() { diff --git a/src/client/refresh.js b/src/client/refresh.js index cabc8da..8896240 100644 --- a/src/client/refresh.js +++ b/src/client/refresh.js @@ -30,6 +30,6 @@ export default function _refresh(options = {}) { metaInfo.changed.call(this, metaInfo, tags.addedTags, tags.removedTags) } - return metaInfo + return { vm: this, metaInfo, tags } } } diff --git a/src/shared/mixin.js b/src/shared/mixin.js index beece7a..8bd2795 100644 --- a/src/shared/mixin.js +++ b/src/shared/mixin.js @@ -81,7 +81,12 @@ export default function createMixin(Vue, options) { next() }) - $router.afterEach(() => $rootMeta.resume()) + $router.afterEach(() => { + const { vm, metaInfo } = $rootMeta.resume() + if (metaInfo && metaInfo.afterNavigation && isFunction(metaInfo.afterNavigation)) { + metaInfo.afterNavigation.call(vm, metaInfo) + } + }) } } } diff --git a/src/shared/options.js b/src/shared/options.js index 65f97f0..eb81847 100644 --- a/src/shared/options.js +++ b/src/shared/options.js @@ -1,4 +1,4 @@ -import { isObject } from './typeof' +import { isObject, isFunction } from './typeof' import { keyName, @@ -29,5 +29,15 @@ export default function setOptions(options) { } } + if (options.afterNavigation && !isFunction(options.afterNavigation)) { + console.warn(`afterNavigation should be a function, received ${typeof options.afterNavigation} instead`) // eslint-disable-line no-console + options.afterNavigation = void 0 + return options + } + + if (options.afterNavigation && !options.refreshOnceOnNavigation) { + options.refreshOnceOnNavigation = true + } + return options } diff --git a/test/plugin-browser.test.js b/test/plugin-browser.test.js index 67b114b..6f5b30e 100644 --- a/test/plugin-browser.test.js +++ b/test/plugin-browser.test.js @@ -100,7 +100,7 @@ describe('plugin', () => { expect(batchUpdateSpy).not.toHaveBeenCalled() jest.clearAllMocks() - const metaInfo = wrapper.vm.$meta().resume() + const { metaInfo } = wrapper.vm.$meta().resume() expect(metaInfo.title).toBe(title) }) })