Skip to content

Commit 0908484

Browse files
committed
handle keep-alive
1 parent 9d9b63b commit 0908484

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

lib/hot-shim.js

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1-
// override component directive's resolveComponent function.
2-
// When component is resolved:
3-
// - remove self from previous component's list
4-
// - add self to current component's list
1+
/**
2+
* override component directive's resolveComponent function.
3+
* When component is resolved:
4+
* - remove self from previous component's list
5+
* - add self to current component's list
6+
*/
57

68
var shimmed = false
7-
module.exports = function (Vue) {
9+
exports.install = function (Vue) {
810
if (shimmed) return
911
shimmed = true
1012
console.log('[HMR] Vue component hot reload shim applied.')
11-
var map = window.map = Vue.config._hotComponents = Object.create(null)
13+
var map = Vue.config._hotComponents = Object.create(null)
1214
var componentDir = Vue.internalDirectives.component
15+
16+
var set = componentDir.setComponent
17+
componentDir.setComponent = function (id, cb) {
18+
var prevComponent = this.Component
19+
var prevId = prevComponent && prevComponent.options.hotID
20+
if (prevId) {
21+
map[prevId].instances.$remove(this)
22+
}
23+
set.call(this, id, cb)
24+
}
25+
1326
var resolve = componentDir.resolveComponent
1427
componentDir.resolveComponent = function (id, cb) {
1528
var view = this
16-
var prevComponent = view.Component
17-
var prevId = prevComponent && prevComponent.options.hotID
1829
resolve.call(this, id, function () {
1930
var Component = view.Component
2031
var newId = Component.options.hotID
21-
if (prevId) {
22-
map[prevId].instances.$remove(view)
23-
}
2432
if (newId) {
2533
if (!map[newId]) {
2634
map[newId] = {
@@ -33,4 +41,38 @@ module.exports = function (Vue) {
3341
cb()
3442
})
3543
}
44+
45+
var unbind = componentDir.unbind
46+
componentDir.unbind = function () {
47+
var id = this.Component && this.Component.options.hotID
48+
if (id) {
49+
map[id].instances.$remove(this)
50+
}
51+
unbind.call(this)
52+
}
53+
}
54+
55+
/**
56+
* Update a component directive instance
57+
*
58+
* @param {Directive} view
59+
*/
60+
61+
exports.update = function (view) {
62+
if (!view._bound) {
63+
return
64+
}
65+
// disable transitions
66+
view.vm._isCompiled = false
67+
// save state
68+
var state = view.childVM.$data
69+
// remount, make sure to disable keep-alive
70+
var keepAlive = view.keepAlive
71+
view.keepAlive = false
72+
view.mountComponent()
73+
view.keepAlive = keepAlive
74+
// restore state
75+
view.childVM.$data = state
76+
// re-eanble transitions
77+
view.vm._isCompiled = true
3678
}

lib/loader.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
var loaderUtils = require('loader-utils')
22
var selectorPath = require.resolve('./selector')
33
var parserPath = require.resolve('./parser')
4-
var hotShimPath = require.resolve('./hot-shim')
54

65
var defaultLang = {
76
template: 'html',
@@ -119,7 +118,10 @@ module.exports = function (content) {
119118
}
120119

121120
// hot reload
122-
if (parts.script.length || parts.template.length) {
121+
if (
122+
process.env.NODE_ENV !== 'production' &&
123+
(parts.script.length || parts.template.length)
124+
) {
123125
var scriptString = parts.script.length ? getRequireString('script', parts.script[0], 0) : ''
124126
var templateString = parts.template.length ? getRequireString('template', parts.template[0], 0, hasLocalStyles) : ''
125127
var accepted = []
@@ -135,22 +137,20 @@ module.exports = function (content) {
135137
// shim the component directive so that it
136138
// registers the instances
137139
'var Vue = require("vue")\n' +
138-
'require("' + hotShimPath + '")(Vue)\n' +
140+
'var shim = require("' + require.resolve('./hot-shim') + '")\n' +
141+
'shim.install(Vue)\n' +
139142
'var map = Vue.config._hotComponents\n' +
140143
'var id = module.exports.hotID = ' + (scriptString || templateString) + '\n' +
141144
'module.hot.accept(' + JSON.stringify(accepted) + ', function () {\n' +
142145
'var Ctor = map[id].Ctor\n' +
143-
// overwrite existing constructor's options
146+
// overwrite existing constructor's options
144147
(scriptString ? 'Ctor.options = Vue.util.mergeOptions(Vue.options, require(' + scriptString + '))\n' : '') +
145148
(templateString ? 'Ctor.options.template = require(' + templateString + ')\n' : '') +
146149
// reset linker
147150
'Ctor.linker = null\n' +
148151
// reload directive instances
149-
'map[id].instances.forEach(function (view) {\n' +
150-
'var state = view.childVM.$data\n' +
151-
'view.mountComponent()\n' +
152-
'view.childVM.$data = state\n' +
153-
'})\n' +
152+
'map[id].instances.forEach(shim.update)\n' +
153+
// re-enable transitions
154154
'})\n' +
155155
'})()\n' +
156156
'}'

0 commit comments

Comments
 (0)