55 * - add self to current component's list
66 */
77
8+ var Vue
9+ var map = Object . create ( null )
810var shimmed = false
9- exports . install = function ( Vue ) {
11+
12+ exports . install = function ( vue ) {
1013 if ( shimmed ) return
1114 shimmed = true
12-
15+
16+ Vue = vue
1317 exports . compatible = ! ! Vue . internalDirectives
1418 if ( ! exports . compatible ) {
1519 console . warn (
@@ -19,15 +23,13 @@ exports.install = function (Vue) {
1923 return
2024 }
2125
22- // create global hot reload map
23- var map = Vue . config . _hotComponents = Object . create ( null )
2426 // shim component
25- shimComponent ( Vue . internalDirectives . component , map )
27+ shimComponent ( Vue . internalDirectives . component )
2628 console . log ( '[HMR] vue component hot reload shim applied.' )
2729 // shim router-view if present
2830 var routerView = Vue . elementDirective ( 'router-view' )
2931 if ( routerView ) {
30- shimComponent ( routerView , map )
32+ shimComponent ( routerView )
3133 console . log ( '[HMR] vue-router <router-view> hot reload shim applied.' )
3234 }
3335}
@@ -36,18 +38,17 @@ exports.install = function (Vue) {
3638 * Shim the component directive.
3739 *
3840 * @param {Object } dir
39- * @param {Object } map - hot component map
4041 */
4142
42- function shimComponent ( dir , map ) {
43+ function shimComponent ( dir ) {
4344 shimMethod ( dir , 'unbuild' , function ( defer ) {
4445 if ( ! this . hotUpdating ) {
4546 var prevComponent = this . childVM && this . childVM . constructor
46- removeComponent ( prevComponent , map , this )
47+ removeComponent ( prevComponent , this )
4748 // defer = true means we are transitioning to a new
4849 // Component. Register this new component to the list.
4950 if ( defer ) {
50- addComponent ( this . Component , map , this )
51+ addComponent ( this . Component , this )
5152 }
5253 }
5354 } )
@@ -73,36 +74,99 @@ function shimMethod (dir, methodName, fn) {
7374 * Remove a component view from a Component's hot list
7475 *
7576 * @param {Function } Component
76- * @param {Object } map - hot component map
7777 * @param {Directive } view - view directive instance
7878 */
7979
80- function removeComponent ( Component , map , view ) {
80+ function removeComponent ( Component , view ) {
8181 var id = Component && Component . options . hotID
8282 if ( id ) {
83- map [ id ] . instances . $remove ( view )
83+ map [ id ] . views . $remove ( view )
8484 }
8585}
8686
8787/**
8888 * Add a component view to a Component's hot list
8989 *
9090 * @param {Function } Component
91- * @param {Object } map - hot component map
9291 * @param {Directive } view - view directive instance
9392 */
9493
95- function addComponent ( Component , map , view ) {
94+ function addComponent ( Component , view ) {
9695 var id = Component && Component . options . hotID
9796 if ( id ) {
9897 if ( ! map [ id ] ) {
9998 map [ id ] = {
100- Ctor : Component ,
99+ Component : Component ,
100+ views : [ ] ,
101101 instances : [ ]
102102 }
103103 }
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
105165 }
166+ // reset constructor cached linker
167+ Component . linker = null
168+ // reload all views
169+ record . views . forEach ( updateView )
106170}
107171
108172/**
@@ -111,7 +175,7 @@ function addComponent (Component, map, view) {
111175 * @param {Directive } view
112176 */
113177
114- exports . update = function ( view ) {
178+ function updateView ( view ) {
115179 if ( ! view . _bound ) {
116180 return
117181 }
0 commit comments