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) var promise = promisify(Component.options.asyncData, context)
promise.then((asyncDataResult) => { promise.then((asyncDataResult) => {
let data = {} let data = {}
// keep asyncData() result
Component._asyncDataResult = asyncDataResult
// Call data() if defined // Call data() if defined
if (Component.options.data && typeof Component.options.data === 'function') { if (Component.options.data && typeof Component.options.data === 'function') {
data = Component.options.data() 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) { function hotReloadAPI (_app) {
if (!module.hot) return if (!module.hot) return
const $nuxt = _app.$nuxt let $components = []
if ($nuxt._hasHotReload) return let $nuxt = _app.$nuxt
$nuxt._hasHotReload = true while ($nuxt && $nuxt.$children && $nuxt.$children.length) {
var _forceUpdate = $nuxt.$forceUpdate.bind($nuxt) $nuxt.$children.forEach(function (child, i) {
$nuxt.$forceUpdate = function () { if (child.$vnode.data.nuxtChild) {
let Component = getMatchedComponents(router.currentRoute)[0] 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 (!Component) return _forceUpdate()
if (typeof Component === 'object' && !Component.options) { if (typeof Component === 'object' && !Component.options) {
// Updated via vue-router resolveAsyncComponents() // Updated via vue-router resolveAsyncComponents()
Component = Vue.extend(Component) Component = Vue.extend(Component)
Component._Ctor = Component Component._Ctor = Component
} }
_app.error() this.error()
let promises = [] let promises = []
// If layout changed if (depth === 0) {
Component.options.layout = Component.options.layout || 'default' // If layout changed
if (_app.layoutName !== Component.options.layout) { Component.options.layout = Component.options.layout || 'default'
let promise = _app.loadLayout(Component.options.layout) if (this.layoutName !== Component.options.layout) {
promise.then(() => { let promise = this.loadLayout(Component.options.layout)
_app.setLayout(Component.options.layout) promise.then(() => {
Vue.nextTick(() => hotReloadAPI(_app)) this.setLayout(Component.options.layout)
}) Vue.nextTick(() => hotReloadAPI(this))
promises.push(promise) })
promises.push(promise)
}
} }
const next = function (path) { const next = function (path) {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
router.push(path) 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() // Call asyncData()
let pAsyncData = promisify(Component.options.asyncData || noopData, context) let pAsyncData = promisify(Component.options.asyncData || noopData, context)
pAsyncData.then((asyncDataResult) => { pAsyncData.then((asyncDataResult) => {
@ -272,6 +293,7 @@ function hotReloadAPI (_app) {
return Promise.all(promises).then(() => { return Promise.all(promises).then(() => {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
_forceUpdate() _forceUpdate()
setTimeout(() => hotReloadAPI(this), 100)
}) })
} }
} }