Fix hotReloading for children

This commit is contained in:
Sébastien Chopin 2017-03-16 18:52:06 +01:00
parent 8287639507
commit 65eeff332e

View File

@ -135,8 +135,6 @@ function render (to, from, next) {
var promise = promisify(Component.options.asyncData, context)
promise.then((asyncDataResult) => {
let data = {}
// keep asyncData() result
Component._asyncDataResult = asyncDataResult
// Call data() if defined
if (Component.options.data && typeof Component.options.data === 'function') {
data = Component.options.data()
@ -220,38 +218,61 @@ function fixPrepatch (to, ___) {
})
}
// Special hot reload with data(context)
// Special hot reload with asyncData(context)
function hotReloadAPI (_app) {
if (!module.hot) return
const $nuxt = _app.$nuxt
if ($nuxt._hasHotReload) return
$nuxt._hasHotReload = true
var _forceUpdate = $nuxt.$forceUpdate.bind($nuxt)
$nuxt.$forceUpdate = function () {
let Component = getMatchedComponents(router.currentRoute)[0]
let $components = []
let $nuxt = _app.$nuxt
while ($nuxt && $nuxt.$children && $nuxt.$children.length) {
$nuxt.$children.forEach(function (child, i) {
if (child.$vnode.data.nuxtChild) {
let hasAlready = false
$components.forEach(function (component) {
if (component.$options.__file === child.$options.__file) {
hasAlready = true
}
})
if (!hasAlready) {
$components.push(child)
}
}
$nuxt = child
})
}
$components.forEach(addHotReload.bind(_app))
}
function addHotReload ($component, depth) {
if ($component.$vnode.data._hasHotReload) return
$component.$vnode.data._hasHotReload = true
var _forceUpdate = $component.$forceUpdate.bind($component.$parent)
$component.$vnode.context.$forceUpdate = () => {
let Component = getMatchedComponents(router.currentRoute)[depth]
if (!Component) return _forceUpdate()
if (typeof Component === 'object' && !Component.options) {
// Updated via vue-router resolveAsyncComponents()
Component = Vue.extend(Component)
Component._Ctor = Component
}
_app.error()
this.error()
let promises = []
// If layout changed
Component.options.layout = Component.options.layout || 'default'
if (_app.layoutName !== Component.options.layout) {
let promise = _app.loadLayout(Component.options.layout)
promise.then(() => {
_app.setLayout(Component.options.layout)
Vue.nextTick(() => hotReloadAPI(_app))
})
promises.push(promise)
if (depth === 0) {
// If layout changed
Component.options.layout = Component.options.layout || 'default'
if (this.layoutName !== Component.options.layout) {
let promise = this.loadLayout(Component.options.layout)
promise.then(() => {
this.setLayout(Component.options.layout)
Vue.nextTick(() => hotReloadAPI(this))
})
promises.push(promise)
}
}
const next = function (path) {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
router.push(path)
}
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: _app.error })
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: this.error })
// Call asyncData()
let pAsyncData = promisify(Component.options.asyncData || noopData, context)
pAsyncData.then((asyncDataResult) => {
@ -272,6 +293,7 @@ function hotReloadAPI (_app) {
return Promise.all(promises).then(() => {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
_forceUpdate()
setTimeout(() => hotReloadAPI(this), 100)
})
}
}