274 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			274 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var Vue // late bind
 | 
						|
var version
 | 
						|
var map = Object.create(null)
 | 
						|
if (typeof window !== 'undefined') {
 | 
						|
  window.__VUE_HOT_MAP__ = map
 | 
						|
}
 | 
						|
var installed = false
 | 
						|
var isBrowserify = false
 | 
						|
var initHookName = 'beforeCreate'
 | 
						|
 | 
						|
exports.install = function (vue, browserify) {
 | 
						|
  if (installed) { return }
 | 
						|
  installed = true
 | 
						|
 | 
						|
  Vue = vue.__esModule ? vue.default : vue
 | 
						|
  version = Vue.version.split('.').map(Number)
 | 
						|
  isBrowserify = browserify
 | 
						|
 | 
						|
  // compat with < 2.0.0-alpha.7
 | 
						|
  if (Vue.config._lifecycleHooks.indexOf('init') > -1) {
 | 
						|
    initHookName = 'init'
 | 
						|
  }
 | 
						|
 | 
						|
  exports.compatible = version[0] >= 2
 | 
						|
  if (!exports.compatible) {
 | 
						|
    console.warn(
 | 
						|
      '[HMR] You are using a version of vue-hot-reload-api that is ' +
 | 
						|
        'only compatible with Vue.js core ^2.0.0.'
 | 
						|
    )
 | 
						|
    return
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Create a record for a hot module, which keeps track of its constructor
 | 
						|
 * and instances
 | 
						|
 *
 | 
						|
 * @param {String} id
 | 
						|
 * @param {Object} options
 | 
						|
 */
 | 
						|
 | 
						|
exports.createRecord = function (id, options) {
 | 
						|
  if(map[id]) { return }
 | 
						|
 | 
						|
  var Ctor = null
 | 
						|
  if (typeof options === 'function') {
 | 
						|
    Ctor = options
 | 
						|
    options = Ctor.options
 | 
						|
  }
 | 
						|
  makeOptionsHot(id, options)
 | 
						|
  map[id] = {
 | 
						|
    Ctor: Ctor,
 | 
						|
    options: options,
 | 
						|
    instances: []
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Check if module is recorded
 | 
						|
 *
 | 
						|
 * @param {String} id
 | 
						|
 */
 | 
						|
 | 
						|
exports.isRecorded = function (id) {
 | 
						|
  return typeof map[id] !== 'undefined'
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Make a Component options object hot.
 | 
						|
 *
 | 
						|
 * @param {String} id
 | 
						|
 * @param {Object} options
 | 
						|
 */
 | 
						|
 | 
						|
function makeOptionsHot(id, options) {
 | 
						|
  if (options.functional) {
 | 
						|
    var render = options.render
 | 
						|
    options.render = function (h, ctx) {
 | 
						|
      var instances = map[id].instances
 | 
						|
      if (ctx && instances.indexOf(ctx.parent) < 0) {
 | 
						|
        instances.push(ctx.parent)
 | 
						|
      }
 | 
						|
      return render(h, ctx)
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    injectHook(options, initHookName, function() {
 | 
						|
      var record = map[id]
 | 
						|
      if (!record.Ctor) {
 | 
						|
        record.Ctor = this.constructor
 | 
						|
      }
 | 
						|
      record.instances.push(this)
 | 
						|
    })
 | 
						|
    injectHook(options, 'beforeDestroy', function() {
 | 
						|
      var instances = map[id].instances
 | 
						|
      instances.splice(instances.indexOf(this), 1)
 | 
						|
    })
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Inject a hook to a hot reloadable component so that
 | 
						|
 * we can keep track of it.
 | 
						|
 *
 | 
						|
 * @param {Object} options
 | 
						|
 * @param {String} name
 | 
						|
 * @param {Function} hook
 | 
						|
 */
 | 
						|
 | 
						|
function injectHook(options, name, hook) {
 | 
						|
  var existing = options[name]
 | 
						|
  options[name] = existing
 | 
						|
    ? Array.isArray(existing) ? existing.concat(hook) : [existing, hook]
 | 
						|
    : [hook]
 | 
						|
}
 | 
						|
 | 
						|
function tryWrap(fn) {
 | 
						|
  return function (id, arg) {
 | 
						|
    try {
 | 
						|
      fn(id, arg)
 | 
						|
    } catch (e) {
 | 
						|
      console.error(e)
 | 
						|
      console.warn(
 | 
						|
        'Something went wrong during Vue component hot-reload. Full reload required.'
 | 
						|
      )
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function updateOptions (oldOptions, newOptions) {
 | 
						|
  for (var key in oldOptions) {
 | 
						|
    if (!(key in newOptions)) {
 | 
						|
      delete oldOptions[key]
 | 
						|
    }
 | 
						|
  }
 | 
						|
  for (var key$1 in newOptions) {
 | 
						|
    oldOptions[key$1] = newOptions[key$1]
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
exports.rerender = tryWrap(function (id, options) {
 | 
						|
  var record = map[id]
 | 
						|
  if (!options) {
 | 
						|
    record.instances.slice().forEach(function (instance) {
 | 
						|
      instance.$forceUpdate()
 | 
						|
    })
 | 
						|
    return
 | 
						|
  }
 | 
						|
  if (typeof options === 'function') {
 | 
						|
    options = options.options
 | 
						|
  }
 | 
						|
  if (record.Ctor) {
 | 
						|
    record.Ctor.options.render = options.render
 | 
						|
    record.Ctor.options.staticRenderFns = options.staticRenderFns
 | 
						|
    record.instances.slice().forEach(function (instance) {
 | 
						|
      instance.$options.render = options.render
 | 
						|
      instance.$options.staticRenderFns = options.staticRenderFns
 | 
						|
      // reset static trees
 | 
						|
      // pre 2.5, all static trees are cached together on the instance
 | 
						|
      if (instance._staticTrees) {
 | 
						|
        instance._staticTrees = []
 | 
						|
      }
 | 
						|
      // 2.5.0
 | 
						|
      if (Array.isArray(record.Ctor.options.cached)) {
 | 
						|
        record.Ctor.options.cached = []
 | 
						|
      }
 | 
						|
      // 2.5.3
 | 
						|
      if (Array.isArray(instance.$options.cached)) {
 | 
						|
        instance.$options.cached = []
 | 
						|
      }
 | 
						|
 | 
						|
      // post 2.5.4: v-once trees are cached on instance._staticTrees.
 | 
						|
      // Pure static trees are cached on the staticRenderFns array
 | 
						|
      // (both already reset above)
 | 
						|
 | 
						|
      // 2.6: temporarily mark rendered scoped slots as unstable so that
 | 
						|
      // child components can be forced to update
 | 
						|
      var restore = patchScopedSlots(instance)
 | 
						|
      instance.$forceUpdate()
 | 
						|
      instance.$nextTick(restore)
 | 
						|
    })
 | 
						|
  } else {
 | 
						|
    // functional or no instance created yet
 | 
						|
    record.options.render = options.render
 | 
						|
    record.options.staticRenderFns = options.staticRenderFns
 | 
						|
 | 
						|
    // handle functional component re-render
 | 
						|
    if (record.options.functional) {
 | 
						|
      // rerender with full options
 | 
						|
      if (Object.keys(options).length > 2) {
 | 
						|
        updateOptions(record.options, options)
 | 
						|
      } else {
 | 
						|
        // template-only rerender.
 | 
						|
        // need to inject the style injection code for CSS modules
 | 
						|
        // to work properly.
 | 
						|
        var injectStyles = record.options._injectStyles
 | 
						|
        if (injectStyles) {
 | 
						|
          var render = options.render
 | 
						|
          record.options.render = function (h, ctx) {
 | 
						|
            injectStyles.call(ctx)
 | 
						|
            return render(h, ctx)
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      record.options._Ctor = null
 | 
						|
      // 2.5.3
 | 
						|
      if (Array.isArray(record.options.cached)) {
 | 
						|
        record.options.cached = []
 | 
						|
      }
 | 
						|
      record.instances.slice().forEach(function (instance) {
 | 
						|
        instance.$forceUpdate()
 | 
						|
      })
 | 
						|
    }
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
exports.reload = tryWrap(function (id, options) {
 | 
						|
  var record = map[id]
 | 
						|
  if (options) {
 | 
						|
    if (typeof options === 'function') {
 | 
						|
      options = options.options
 | 
						|
    }
 | 
						|
    makeOptionsHot(id, options)
 | 
						|
    if (record.Ctor) {
 | 
						|
      if (version[1] < 2) {
 | 
						|
        // preserve pre 2.2 behavior for global mixin handling
 | 
						|
        record.Ctor.extendOptions = options
 | 
						|
      }
 | 
						|
      var newCtor = record.Ctor.super.extend(options)
 | 
						|
      // prevent record.options._Ctor from being overwritten accidentally
 | 
						|
      newCtor.options._Ctor = record.options._Ctor
 | 
						|
      record.Ctor.options = newCtor.options
 | 
						|
      record.Ctor.cid = newCtor.cid
 | 
						|
      record.Ctor.prototype = newCtor.prototype
 | 
						|
      if (newCtor.release) {
 | 
						|
        // temporary global mixin strategy used in < 2.0.0-alpha.6
 | 
						|
        newCtor.release()
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      updateOptions(record.options, options)
 | 
						|
    }
 | 
						|
  }
 | 
						|
  record.instances.slice().forEach(function (instance) {
 | 
						|
    if (instance.$vnode && instance.$vnode.context) {
 | 
						|
      instance.$vnode.context.$forceUpdate()
 | 
						|
    } else {
 | 
						|
      console.warn(
 | 
						|
        'Root or manually mounted instance modified. Full reload required.'
 | 
						|
      )
 | 
						|
    }
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
// 2.6 optimizes template-compiled scoped slots and skips updates if child
 | 
						|
// only uses scoped slots. We need to patch the scoped slots resolving helper
 | 
						|
// to temporarily mark all scoped slots as unstable in order to force child
 | 
						|
// updates.
 | 
						|
function patchScopedSlots (instance) {
 | 
						|
  if (!instance._u) { return }
 | 
						|
  // https://github.com/vuejs/vue/blob/dev/src/core/instance/render-helpers/resolve-scoped-slots.js
 | 
						|
  var original = instance._u
 | 
						|
  instance._u = function (slots) {
 | 
						|
    try {
 | 
						|
      // 2.6.4 ~ 2.6.6
 | 
						|
      return original(slots, true)
 | 
						|
    } catch (e) {
 | 
						|
      // 2.5 / >= 2.6.7
 | 
						|
      return original(slots, null, true)
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return function () {
 | 
						|
    instance._u = original
 | 
						|
  }
 | 
						|
}
 |