@@ -29,130 +29,136 @@ export default function createMixin (Vue, options) {
29
29
// Add a marker to know if it uses metaInfo
30
30
// _vnode is used to know that it's attached to a real component
31
31
// useful if we use some mixin to add some meta tags (like nuxt-i18n)
32
- if ( ! isUndefined ( this . $options [ options . keyName ] ) && this . $options [ options . keyName ] !== null ) {
33
- if ( ! this . $root . _vueMeta ) {
34
- this . $root . _vueMeta = { appId }
35
- appId ++
36
- }
32
+ if ( isUndefined ( this . $options [ options . keyName ] ) || this . $options [ options . keyName ] === null ) {
33
+ return
34
+ }
37
35
38
- // to speed up updates we keep track of branches which have a component with vue-meta info defined
39
- // if _vueMeta = true it has info, if _vueMeta = false a child has info
40
- if ( ! this . _vueMeta ) {
41
- this . _vueMeta = true
36
+ if ( ! this . $root . _vueMeta ) {
37
+ this . $root . _vueMeta = { appId }
38
+ appId ++
39
+ }
42
40
43
- let p = this . $parent
44
- while ( p && p !== this . $root ) {
45
- if ( isUndefined ( p . _vueMeta ) ) {
46
- p . _vueMeta = false
47
- }
48
- p = p . $parent
41
+ // to speed up updates we keep track of branches which have a component with vue-meta info defined
42
+ // if _vueMeta = true it has info, if _vueMeta = false a child has info
43
+ if ( ! this . _vueMeta ) {
44
+ this . _vueMeta = true
45
+
46
+ let p = this . $parent
47
+ while ( p && p !== this . $root ) {
48
+ if ( isUndefined ( p . _vueMeta ) ) {
49
+ p . _vueMeta = false
49
50
}
51
+ p = p . $parent
50
52
}
53
+ }
51
54
52
- // coerce function-style metaInfo to a computed prop so we can observe
53
- // it on creation
54
- if ( isFunction ( this . $options [ options . keyName ] ) ) {
55
- if ( ! this . $options . computed ) {
56
- this . $options . computed = { }
57
- }
58
- this . $options . computed . $metaInfo = this . $options [ options . keyName ]
59
-
60
- if ( ! this . $isServer ) {
61
- // if computed $metaInfo exists, watch it for updates & trigger a refresh
62
- // when it changes (i.e. automatically handle async actions that affect metaInfo)
63
- // credit for this suggestion goes to [Sébastien Chopin](https://github.com/Atinux)
64
- ensuredPush ( this . $options , 'created' , ( ) => {
65
- this . $watch ( '$metaInfo' , function ( ) {
66
- triggerUpdate ( this , 'watcher' )
67
- } )
68
- } )
69
- }
55
+ // coerce function-style metaInfo to a computed prop so we can observe
56
+ // it on creation
57
+ if ( isFunction ( this . $options [ options . keyName ] ) ) {
58
+ if ( ! this . $options . computed ) {
59
+ this . $options . computed = { }
70
60
}
61
+ this . $options . computed . $metaInfo = this . $options [ options . keyName ]
71
62
72
- // force an initial refresh on page load and prevent other lifecycleHooks
73
- // to triggerUpdate until this initial refresh is finished
74
- // this is to make sure that when a page is opened in an inactive tab which
75
- // has throttled rAF/timers we still immediately set the page title
76
- if ( isUndefined ( this . $root . _vueMeta . initialized ) ) {
77
- this . $root . _vueMeta . initialized = this . $isServer
78
-
79
- if ( ! this . $root . _vueMeta . initialized ) {
80
- ensuredPush ( this . $options , 'beforeMount' , ( ) => {
81
- // if this Vue-app was server rendered, set the appId to 'ssr'
82
- // only one SSR app per page is supported
83
- if ( this . $root . $el && this . $root . $el . hasAttribute && this . $root . $el . hasAttribute ( 'data-server-rendered' ) ) {
84
- this . $root . _vueMeta . appId = options . ssrAppId
85
- }
63
+ if ( ! this . $isServer ) {
64
+ // if computed $metaInfo exists, watch it for updates & trigger a refresh
65
+ // when it changes (i.e. automatically handle async actions that affect metaInfo)
66
+ // credit for this suggestion goes to [Sébastien Chopin](https://github.com/Atinux)
67
+ ensuredPush ( this . $options , 'created' , ( ) => {
68
+ this . $watch ( '$metaInfo' , ( ) => {
69
+ this . __metaInfo = undefined
70
+ triggerUpdate ( this , 'watcher' )
86
71
} )
72
+ } )
73
+ }
74
+ }
87
75
88
- // we use the mounted hook here as on page load
89
- ensuredPush ( this . $options , 'mounted' , ( ) => {
90
- if ( ! this . $root . _vueMeta . initialized ) {
91
- // used in triggerUpdate to check if a change was triggered
92
- // during initialization
93
- this . $root . _vueMeta . initializing = true
94
-
95
- // refresh meta in nextTick so all child components have loaded
96
- this . $nextTick ( function ( ) {
97
- const { tags, metaInfo } = this . $root . $meta ( ) . refresh ( )
98
-
99
- // After ssr hydration (identifier by tags === false) check
100
- // if initialized was set to null in triggerUpdate. That'd mean
101
- // that during initilazation changes where triggered which need
102
- // to be applied OR a metaInfo watcher was triggered before the
103
- // current hook was called
104
- // (during initialization all changes are blocked)
105
- if ( tags === false && this . $root . _vueMeta . initialized === null ) {
106
- this . $nextTick ( ( ) => triggerUpdate ( this , 'initializing' ) )
107
- }
108
-
109
- this . $root . _vueMeta . initialized = true
110
- delete this . $root . _vueMeta . initializing
111
-
112
- // add the navigation guards if they havent been added yet
113
- // they are needed for the afterNavigation callback
114
- if ( ! options . refreshOnceOnNavigation && metaInfo . afterNavigation ) {
115
- addNavGuards ( this )
116
- }
117
- } )
118
- }
119
- } )
76
+ // force an initial refresh on page load and prevent other lifecycleHooks
77
+ // to triggerUpdate until this initial refresh is finished
78
+ // this is to make sure that when a page is opened in an inactive tab which
79
+ // has throttled rAF/timers we still immediately set the page title
80
+ if ( isUndefined ( this . $root . _vueMeta . initialized ) ) {
81
+ this . $root . _vueMeta . initialized = this . $isServer
82
+
83
+ if ( ! this . $root . _vueMeta . initialized ) {
84
+ ensuredPush ( this . $options , 'beforeMount' , ( ) => {
85
+ // if this Vue-app was server rendered, set the appId to 'ssr'
86
+ // only one SSR app per page is supported
87
+ if ( this . $root . $el && this . $root . $el . hasAttribute && this . $root . $el . hasAttribute ( 'data-server-rendered' ) ) {
88
+ this . $root . _vueMeta . appId = options . ssrAppId
89
+ }
90
+ } )
120
91
121
- // add the navigation guards if requested
122
- if ( options . refreshOnceOnNavigation ) {
123
- addNavGuards ( this )
92
+ // we use the mounted hook here as on page load
93
+ ensuredPush ( this . $options , 'mounted' , ( ) => {
94
+ if ( ! this . $root . _vueMeta . initialized ) {
95
+ // used in triggerUpdate to check if a change was triggered
96
+ // during initialization
97
+ this . $root . _vueMeta . initializing = true
98
+
99
+ // refresh meta in nextTick so all child components have loaded
100
+ this . $nextTick ( function ( ) {
101
+ const { tags, metaInfo } = this . $root . $meta ( ) . refresh ( )
102
+
103
+ // After ssr hydration (identifier by tags === false) check
104
+ // if initialized was set to null in triggerUpdate. That'd mean
105
+ // that during initilazation changes where triggered which need
106
+ // to be applied OR a metaInfo watcher was triggered before the
107
+ // current hook was called
108
+ // (during initialization all changes are blocked)
109
+ if ( tags === false && this . $root . _vueMeta . initialized === null ) {
110
+ this . $nextTick ( ( ) => triggerUpdate ( this , 'initializing' ) )
111
+ }
112
+
113
+ this . $root . _vueMeta . initialized = true
114
+ delete this . $root . _vueMeta . initializing
115
+
116
+ // add the navigation guards if they havent been added yet
117
+ // they are needed for the afterNavigation callback
118
+ if ( ! options . refreshOnceOnNavigation && metaInfo . afterNavigation ) {
119
+ addNavGuards ( this )
120
+ }
121
+ } )
124
122
}
123
+ } )
124
+
125
+ // add the navigation guards if requested
126
+ if ( options . refreshOnceOnNavigation ) {
127
+ addNavGuards ( this )
125
128
}
126
129
}
130
+ }
127
131
128
- // do not trigger refresh on the server side
129
- if ( ! this . $isServer ) {
130
- // no need to add this hooks on server side
131
- updateOnLifecycleHook . forEach ( ( lifecycleHook ) => {
132
- ensuredPush ( this . $options , lifecycleHook , ( ) => triggerUpdate ( this , lifecycleHook ) )
133
- } )
132
+ // do not trigger refresh on the server side
133
+ if ( this . $isServer ) {
134
+ return
135
+ }
134
136
135
- // re-render meta data when returning from a child component to parent
136
- ensuredPush ( this . $options , 'destroyed' , ( ) => {
137
- // Wait that element is hidden before refreshing meta tags (to support animations)
138
- const interval = setInterval ( ( ) => {
139
- if ( this . $el && this . $el . offsetParent !== null ) {
140
- /* istanbul ignore next line */
141
- return
142
- }
137
+ // no need to add this hooks on server side
138
+ updateOnLifecycleHook . forEach ( ( lifecycleHook ) => {
139
+ ensuredPush ( this . $options , lifecycleHook , ( ) => triggerUpdate ( this , lifecycleHook ) )
140
+ } )
141
+ } ,
142
+ // TODO: move back into beforeCreate when Vue issue is resolved
143
+ destroyed ( ) {
144
+ // do not trigger refresh:
145
+ // - on the server side
146
+ // - when the component doesnt have a parent
147
+ // - doesnt have metaInfo defined
148
+ if ( this . $isServer || ! this . $parent || ! hasMetaInfo ( this ) ) {
149
+ return
150
+ }
143
151
144
- clearInterval ( interval )
152
+ // Wait that element is hidden before refreshing meta tags (to support animations)
153
+ const interval = setInterval ( ( ) => {
154
+ if ( this . $el && this . $el . offsetParent !== null ) {
155
+ return
156
+ }
145
157
146
- if ( ! this . $parent ) {
147
- /* istanbul ignore next line */
148
- return
149
- }
158
+ clearInterval ( interval )
150
159
151
- triggerUpdate ( this , 'destroyed' )
152
- } , 50 )
153
- } )
154
- }
155
- }
160
+ triggerUpdate ( this , 'destroyed' )
161
+ } , 50 )
156
162
}
157
163
}
158
164
}
0 commit comments