Skip to content

Commit 21621e1

Browse files
committed
fix: memory leak, use hook events (thanks #522)
1 parent 9655a81 commit 21621e1

File tree

2 files changed

+34
-41
lines changed

2 files changed

+34
-41
lines changed

src/shared/mixin.js

+34-35
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { triggerUpdate } from '../client/update'
22
import { isUndefined, isFunction } from '../utils/is-type'
33
import { find } from '../utils/array'
4-
import { ensuredPush } from '../utils/ensure'
54
import { rootConfigKey } from './constants'
65
import { hasMetaInfo } from './meta-helpers'
76
import { addNavGuards } from './nav-guards'
@@ -80,7 +79,7 @@ export default function createMixin (Vue, options) {
8079
// if computed $metaInfo exists, watch it for updates & trigger a refresh
8180
// when it changes (i.e. automatically handle async actions that affect metaInfo)
8281
// credit for this suggestion goes to [Sébastien Chopin](https://github.com/Atinux)
83-
ensuredPush($options, 'created', function () {
82+
this.$on('hook:created', function () {
8483
this.$watch('$metaInfo', function () {
8584
triggerUpdate(options, this[rootKey], 'watcher')
8685
})
@@ -99,7 +98,7 @@ export default function createMixin (Vue, options) {
9998
if (!$root[rootConfigKey].initializedSsr) {
10099
$root[rootConfigKey].initializedSsr = true
101100

102-
ensuredPush($options, 'beforeMount', function () {
101+
this.$on('hook:beforeMount', function () {
103102
const $root = this
104103
// if this Vue-app was server rendered, set the appId to 'ssr'
105104
// only one SSR app per page is supported
@@ -110,7 +109,7 @@ export default function createMixin (Vue, options) {
110109
}
111110

112111
// we use the mounted hook here as on page load
113-
ensuredPush($options, 'mounted', function () {
112+
this.$on('hook:mounted', function () {
114113
const $root = this[rootKey]
115114

116115
if (!$root[rootConfigKey].initialized) {
@@ -150,6 +149,36 @@ export default function createMixin (Vue, options) {
150149
}
151150
}
152151

152+
this.$on('hook:destroyed', function () {
153+
// do not trigger refresh:
154+
// - when user configured to not wait for transitions on destroyed
155+
// - when the component doesnt have a parent
156+
// - doesnt have metaInfo defined
157+
if (!this.$parent || !hasMetaInfo(this)) {
158+
return
159+
}
160+
delete this._hasMetaInfo
161+
162+
this.$nextTick(() => {
163+
if (!options.waitOnDestroyed || !this.$el || !this.$el.offsetParent) {
164+
triggerUpdate(options, this.$root, 'destroyed')
165+
return
166+
}
167+
168+
// Wait that element is hidden before refreshing meta tags (to support animations)
169+
const interval = setInterval(() => {
170+
if (this.$el && this.$el.offsetParent !== null) {
171+
/* istanbul ignore next line */
172+
return
173+
}
174+
175+
clearInterval(interval)
176+
177+
triggerUpdate(options, this.$root, 'destroyed')
178+
}, 50)
179+
})
180+
})
181+
153182
// do not trigger refresh on the server side
154183
if (this.$isServer) {
155184
/* istanbul ignore next */
@@ -158,40 +187,10 @@ export default function createMixin (Vue, options) {
158187

159188
// no need to add this hooks on server side
160189
updateOnLifecycleHook.forEach((lifecycleHook) => {
161-
ensuredPush($options, lifecycleHook, function () {
190+
this.$on(`hook:${lifecycleHook}`, function () {
162191
triggerUpdate(options, this[rootKey], lifecycleHook)
163192
})
164193
})
165-
},
166-
// TODO: move back into beforeCreate when Vue issue is resolved
167-
destroyed () {
168-
// do not trigger refresh:
169-
// - when user configured to not wait for transitions on destroyed
170-
// - when the component doesnt have a parent
171-
// - doesnt have metaInfo defined
172-
if (!this.$parent || !hasMetaInfo(this)) {
173-
return
174-
}
175-
delete this._hasMetaInfo
176-
177-
this.$nextTick(() => {
178-
if (!options.waitOnDestroyed || !this.$el || !this.$el.offsetParent) {
179-
triggerUpdate(options, this.$root, 'destroyed')
180-
return
181-
}
182-
183-
// Wait that element is hidden before refreshing meta tags (to support animations)
184-
const interval = setInterval(() => {
185-
if (this.$el && this.$el.offsetParent !== null) {
186-
/* istanbul ignore next line */
187-
return
188-
}
189-
190-
clearInterval(interval)
191-
192-
triggerUpdate(options, this.$root, 'destroyed')
193-
}, 50)
194-
})
195194
}
196195
}
197196
}

src/utils/ensure.js

-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,3 @@ export function ensureIsArray (arg, key) {
1010
}
1111
return arg
1212
}
13-
14-
export function ensuredPush (object, key, el) {
15-
ensureIsArray(object, key)
16-
17-
object[key].push(el)
18-
}

0 commit comments

Comments
 (0)