145 lines
3.6 KiB
JavaScript
Vendored
145 lines
3.6 KiB
JavaScript
Vendored
var Vue // late bind
|
|
var version
|
|
var map = window.__VUE_HOT_MAP__ = Object.create(null)
|
|
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) {
|
|
var Ctor = null
|
|
if (typeof options === 'function') {
|
|
Ctor = options
|
|
options = Ctor.options
|
|
}
|
|
makeOptionsHot(id, options)
|
|
map[id] = {
|
|
Ctor: Vue.extend(options),
|
|
instances: []
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make a Component options object hot.
|
|
*
|
|
* @param {String} id
|
|
* @param {Object} options
|
|
*/
|
|
|
|
function makeOptionsHot (id, options) {
|
|
injectHook(options, initHookName, function () {
|
|
map[id].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.')
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
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
|
|
instance._staticTrees = [] // reset static trees
|
|
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 (version[1] < 2) {
|
|
// preserve pre 2.2 behavior for global mixin handling
|
|
record.Ctor.extendOptions = options
|
|
}
|
|
var newCtor = record.Ctor.super.extend(options)
|
|
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()
|
|
}
|
|
}
|
|
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.')
|
|
}
|
|
})
|
|
})
|