From f186cadba6aa6c35e2a0245855550a5f4e2b5c54 Mon Sep 17 00:00:00 2001 From: devneko Date: Sun, 29 Oct 2017 11:02:48 +0900 Subject: [PATCH] fix unexpected state reset #1408 --- lib/app/client.js | 9 +++++---- lib/app/utils.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/app/client.js b/lib/app/client.js index 3a98e4de58..77b683a535 100644 --- a/lib/app/client.js +++ b/lib/app/client.js @@ -6,7 +6,7 @@ import { sanitizeComponent, resolveRouteComponents, getMatchedComponents, - getMatchedComponentsInstances, + getChangedComponentsInstances, flatMapComponents, setContext, middlewareSeries, @@ -346,16 +346,17 @@ function showNextPage(to) { // When navigating on a different route but the same component is used, Vue.js // Will not update the instance data, so we have to update $data ourselves -function fixPrepatch (to, ___) { +function fixPrepatch (to, from) { if (this._hashChanged) return Vue.nextTick(() => { - const instances = getMatchedComponentsInstances(to) + const instances = getChangedComponentsInstances(to, from) + var dlen = to.matched.length - instances.length _lastComponentsFiles = instances.map((instance, i) => { if (!instance) return ''; - if (_lastPaths[i] === instance.constructor._path && typeof instance.constructor.options.data === 'function') { + if (_lastPaths[dlen + i] === instance.constructor._path && typeof instance.constructor.options.data === 'function') { const newData = instance.constructor.options.data.call(instance) for (let key in newData) { Vue.set(instance.$data, key, newData[key]) diff --git a/lib/app/utils.js b/lib/app/utils.js index 88626ac9f0..52d4440496 100644 --- a/lib/app/utils.js +++ b/lib/app/utils.js @@ -65,6 +65,48 @@ export function getMatchedComponentsInstances(route) { })) } +function getRouteRecordWithParamNames (route) { + return route.matched.map(m => { + var paramNames = m.path.match(new RegExp(':[^\\/\\?]+', 'g')) + if (paramNames !== null) { + paramNames = paramNames.map(function (name) { + return name.substring(1) + }) + } + return { + routeRecord: m, + paramNames: paramNames + } + }) +} + +export function getChangedComponentsInstances (to, from) { + var records = getRouteRecordWithParamNames(to) + var r = [] + var parentChange = false + for (var i = 0; i < records.length; i++ ) { + var paramNames = records[i].paramNames + var instances = records[i].routeRecord.instances + instances = Object.keys(instances).map(function (key) { + return instances[key] + }) + if (parentChange) { + r = [].concat(r, instances) + } else if (paramNames !== null) { + for (var pi in paramNames) { + var name = paramNames[pi] + if (to.params[name] !== from.params[name]) { + parentChange = true + r = [].concat(r, instances) + break + } + } + } + } + return r +} + + export function flatMapComponents(route, fn) { return Array.prototype.concat.apply([], route.matched.map(function (m, index) { return Object.keys(m.components).map(function (key) {