Skip to content

Commit b2429ab

Browse files
committed
fix(router-view): add passing props to inactive component
1 parent 0c2b1aa commit b2429ab

File tree

3 files changed

+116
-18
lines changed

3 files changed

+116
-18
lines changed

examples/keepalive-view/app.js

+61
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,48 @@ const Home = { template: '<div>home</div>' }
2929

3030
const ViewWithKeepalive = { template: '<keep-alive><router-view></router-view></keep-alive>' }
3131

32+
const Parent = { template: '<router-view />' }
33+
34+
const RequiredProps = {
35+
template: '<div>props from route config is: {{msg}}</div>',
36+
props: {
37+
msg: {
38+
type: String,
39+
required: true
40+
}
41+
}
42+
}
43+
44+
const savedSilent = Vue.config.silent
45+
const savedWarnHandler = Vue.config.warnHandler
46+
47+
const CatchWarn = {
48+
template: `<div>{{catchedWarn ? 'catched missing prop warn' : 'no missing prop warn'}}</div>`,
49+
data () {
50+
return {
51+
catchedWarn: false
52+
}
53+
},
54+
beforeRouteEnter (to, from, next) {
55+
let missPropWarn = false
56+
Vue.config.silent = false
57+
Vue.config.warnHandler = function (msg, vm, trace) {
58+
if (/Missing required prop/i.test(msg)) {
59+
missPropWarn = true
60+
}
61+
}
62+
next(vm => {
63+
vm.catchedWarn = missPropWarn
64+
})
65+
},
66+
beforeRouteLeave (to, from, next) {
67+
// restore vue config
68+
Vue.config.silent = savedSilent
69+
Vue.config.warnHandler = savedWarnHandler
70+
next()
71+
}
72+
}
73+
3274
const router = new VueRouter({
3375
mode: 'history',
3476
base: __dirname,
@@ -80,6 +122,23 @@ const router = new VueRouter({
80122
]
81123
}
82124
]
125+
},
126+
{
127+
path: '/config-required-props',
128+
component: Parent,
129+
children: [
130+
{
131+
path: 'child',
132+
component: RequiredProps,
133+
props: {
134+
msg: 'ok'
135+
}
136+
}
137+
]
138+
},
139+
{
140+
path: '/catch-warn',
141+
component: CatchWarn
83142
}
84143
]
85144
})
@@ -96,6 +155,8 @@ new Vue({
96155
<li><router-link to="/with-guard2">/with-guard2</router-link></li>
97156
<li><router-link to="/one/two/child1">/one/two/child1</router-link></li>
98157
<li><router-link to="/one/two/child2">/one/two/child2</router-link></li>
158+
<li><router-link to="/config-required-props/child">/config-required-props/child</router-link></li>
159+
<li><router-link to="/catch-warn">/catch-warn</router-link></li>
99160
</ul>
100161
<keep-alive>
101162
<router-view class="view"></router-view>

src/components/view.js

+45-17
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,32 @@ export default {
3939

4040
// render previous view if the tree is inactive and kept-alive
4141
if (inactive) {
42-
return h(cache[name], data, children)
42+
const cachedData = cache[name]
43+
const cachedComponent = cachedData && cachedData.component
44+
if (cachedComponent) {
45+
// #2301
46+
// pass props
47+
if (cachedData.configProps) {
48+
passProps(cachedComponent, data, cachedData.route, cachedData.configProps)
49+
}
50+
return h(cachedComponent, data, children)
51+
} else {
52+
// render previous empty view
53+
return h()
54+
}
4355
}
4456

4557
const matched = route.matched[depth]
46-
// render empty node if no matched route
47-
if (!matched) {
58+
const component = matched && matched.components[name]
59+
60+
// render empty node if no matched route or no config component
61+
if (!matched || !component) {
4862
cache[name] = null
4963
return h()
5064
}
5165

52-
const component = cache[name] = matched.components[name]
66+
// cache component
67+
cache[name] = { component }
5368

5469
// attach instance registration hook
5570
// this will be called in the instance's injected lifecycle hooks
@@ -81,25 +96,38 @@ export default {
8196
}
8297
}
8398

84-
// resolve props
85-
let propsToPass = data.props = resolveProps(route, matched.props && matched.props[name])
86-
if (propsToPass) {
87-
// clone to prevent mutation
88-
propsToPass = data.props = extend({}, propsToPass)
89-
// pass non-declared props as attrs
90-
const attrs = data.attrs = data.attrs || {}
91-
for (const key in propsToPass) {
92-
if (!component.props || !(key in component.props)) {
93-
attrs[key] = propsToPass[key]
94-
delete propsToPass[key]
95-
}
96-
}
99+
const configProps = matched.props && matched.props[name]
100+
// pass props
101+
if (configProps) {
102+
// add route and config props to cache data
103+
extend(cache[name], {
104+
route,
105+
configProps
106+
})
107+
passProps(component, data, route, configProps)
97108
}
98109

99110
return h(component, data, children)
100111
}
101112
}
102113

114+
function passProps (component, data, route, configProps) {
115+
// resolve props
116+
let propsToPass = data.props = resolveProps(route, configProps)
117+
if (propsToPass) {
118+
// clone to prevent mutation
119+
propsToPass = data.props = extend({}, propsToPass)
120+
// pass non-declared props as attrs
121+
const attrs = data.attrs = data.attrs || {}
122+
for (const key in propsToPass) {
123+
if (!component.props || !(key in component.props)) {
124+
attrs[key] = propsToPass[key]
125+
delete propsToPass[key]
126+
}
127+
}
128+
}
129+
}
130+
103131
function resolveProps (route, config) {
104132
switch (typeof config) {
105133
case 'undefined':

test/e2e/specs/keepalive-view.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = {
99
browser
1010
.url('http://localhost:8080/keepalive-view/')
1111
.waitForElementVisible('#app', 1000)
12-
.assert.count('li a', 7)
12+
.assert.count('li a', 9)
1313

1414
.click('li:nth-child(1) a')
1515
.assert.containsText('.view', 'index child1')
@@ -44,6 +44,15 @@ module.exports = {
4444
.click('li:nth-child(7) a')
4545
.assert.containsText('.view', 'index child2')
4646

47+
// missing props in nested routes with keep alive
48+
// https://github.com/vuejs/vue-router/issues/2301
49+
.click('li:nth-child(8) a')
50+
.assert.containsText('.view', 'props from route config is: ok')
51+
.click('li:nth-child(9) a')
52+
.assert.containsText('.view', 'no missing prop warn')
53+
.click('li:nth-child(8) a')
54+
.assert.containsText('.view', 'props from route config is: ok')
55+
4756
.end()
4857
}
4958
}

0 commit comments

Comments
 (0)