diff --git a/lib/app/client.js b/lib/app/client.js index b85e261bbd..463fd33f9e 100644 --- a/lib/app/client.js +++ b/lib/app/client.js @@ -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) }) } }