5
5
* - add self to current component's list
6
6
*/
7
7
8
+ var Vue
9
+ var map = Object . create ( null )
8
10
var shimmed = false
9
- exports . install = function ( Vue ) {
11
+
12
+ exports . install = function ( vue ) {
10
13
if ( shimmed ) return
11
14
shimmed = true
12
-
15
+
16
+ Vue = vue
13
17
exports . compatible = ! ! Vue . internalDirectives
14
18
if ( ! exports . compatible ) {
15
19
console . warn (
@@ -19,15 +23,13 @@ exports.install = function (Vue) {
19
23
return
20
24
}
21
25
22
- // create global hot reload map
23
- var map = Vue . config . _hotComponents = Object . create ( null )
24
26
// shim component
25
- shimComponent ( Vue . internalDirectives . component , map )
27
+ shimComponent ( Vue . internalDirectives . component )
26
28
console . log ( '[HMR] vue component hot reload shim applied.' )
27
29
// shim router-view if present
28
30
var routerView = Vue . elementDirective ( 'router-view' )
29
31
if ( routerView ) {
30
- shimComponent ( routerView , map )
32
+ shimComponent ( routerView )
31
33
console . log ( '[HMR] vue-router <router-view> hot reload shim applied.' )
32
34
}
33
35
}
@@ -36,18 +38,17 @@ exports.install = function (Vue) {
36
38
* Shim the component directive.
37
39
*
38
40
* @param {Object } dir
39
- * @param {Object } map - hot component map
40
41
*/
41
42
42
- function shimComponent ( dir , map ) {
43
+ function shimComponent ( dir ) {
43
44
shimMethod ( dir , 'unbuild' , function ( defer ) {
44
45
if ( ! this . hotUpdating ) {
45
46
var prevComponent = this . childVM && this . childVM . constructor
46
- removeComponent ( prevComponent , map , this )
47
+ removeComponent ( prevComponent , this )
47
48
// defer = true means we are transitioning to a new
48
49
// Component. Register this new component to the list.
49
50
if ( defer ) {
50
- addComponent ( this . Component , map , this )
51
+ addComponent ( this . Component , this )
51
52
}
52
53
}
53
54
} )
@@ -73,36 +74,99 @@ function shimMethod (dir, methodName, fn) {
73
74
* Remove a component view from a Component's hot list
74
75
*
75
76
* @param {Function } Component
76
- * @param {Object } map - hot component map
77
77
* @param {Directive } view - view directive instance
78
78
*/
79
79
80
- function removeComponent ( Component , map , view ) {
80
+ function removeComponent ( Component , view ) {
81
81
var id = Component && Component . options . hotID
82
82
if ( id ) {
83
- map [ id ] . instances . $remove ( view )
83
+ map [ id ] . views . $remove ( view )
84
84
}
85
85
}
86
86
87
87
/**
88
88
* Add a component view to a Component's hot list
89
89
*
90
90
* @param {Function } Component
91
- * @param {Object } map - hot component map
92
91
* @param {Directive } view - view directive instance
93
92
*/
94
93
95
- function addComponent ( Component , map , view ) {
94
+ function addComponent ( Component , view ) {
96
95
var id = Component && Component . options . hotID
97
96
if ( id ) {
98
97
if ( ! map [ id ] ) {
99
98
map [ id ] = {
100
- Ctor : Component ,
99
+ Component : Component ,
100
+ views : [ ] ,
101
101
instances : [ ]
102
102
}
103
103
}
104
- map [ id ] . instances . push ( view )
104
+ map [ id ] . views . push ( view )
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Create a record for a hot module, which keeps track of its construcotr,
110
+ * instnaces and views (component directives or router-views).
111
+ *
112
+ * @param {String } id
113
+ * @param {Object } options
114
+ */
115
+
116
+ exports . createRecord = function ( id , options ) {
117
+ if ( typeof options . el !== 'string' && typeof options . data !== 'object' ) {
118
+ var add = function ( ) {
119
+ map [ id ] . instances . push ( this )
120
+ }
121
+ var remove = function ( ) {
122
+ map [ id ] . instances . $remove ( this )
123
+ }
124
+ options . created = options . created
125
+ ? [ options . created , add ]
126
+ : add
127
+ options . beforeDestroy = options . beforeDestroy
128
+ ? [ options . beforeDestroy , remove ]
129
+ : remove
130
+ map [ id ] = {
131
+ Component : Vue . extend ( options ) ,
132
+ views : [ ] ,
133
+ instances : [ ]
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Update a hot component.
140
+ *
141
+ * @param {String } id
142
+ * @param {Object|null } newOptions
143
+ * @param {String|null } newTemplate
144
+ */
145
+
146
+ exports . update = function ( id , newOptions , newTemplate ) {
147
+ var record = map [ id ]
148
+ // force full-reload if an instance of the component is active but is not
149
+ // managed by a view
150
+ if ( ! record || ( record . instances . length && ! record . views . length ) ) {
151
+ throw new Error ( 'Root or manually-mounted instance modified. Full reload is required.' )
152
+ }
153
+ var Component = record . Component
154
+ // update constructor
155
+ if ( newOptions ) {
156
+ Component . options = Vue . util . mergeOptions ( Vue . options , newOptions )
157
+ }
158
+ if ( newTemplate ) {
159
+ Component . options . template = newTemplate
160
+ }
161
+ // handle recursive lookup
162
+ if ( Component . options . name ) {
163
+ console . log ( Component . options )
164
+ Component . options . components [ Component . options . name ] = Component
105
165
}
166
+ // reset constructor cached linker
167
+ Component . linker = null
168
+ // reload all views
169
+ record . views . forEach ( updateView )
106
170
}
107
171
108
172
/**
@@ -111,7 +175,7 @@ function addComponent (Component, map, view) {
111
175
* @param {Directive } view
112
176
*/
113
177
114
- exports . update = function ( view ) {
178
+ function updateView ( view ) {
115
179
if ( ! view . _bound ) {
116
180
return
117
181
}
0 commit comments