Skip to content

Commit a302a33

Browse files
committed
fix(router-view): add passing props to inactive component
1 parent 732c825 commit a302a33

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
@@ -27,6 +27,48 @@ const IndexChild2 = { template: '<div>index child2</div>' }
2727

2828
const Home = { template: '<div>home</div>' }
2929

30+
const Parent = { template: '<router-view />' }
31+
32+
const RequiredProps = {
33+
template: '<div>props from route config is: {{msg}}</div>',
34+
props: {
35+
msg: {
36+
type: String,
37+
required: true
38+
}
39+
}
40+
}
41+
42+
const savedSilent = Vue.config.silent
43+
const savedWarnHandler = Vue.config.warnHandler
44+
45+
const CatchWarn = {
46+
template: `<div>{{catchedWarn ? 'catched missing prop warn' : 'no missing prop warn'}}</div>`,
47+
data () {
48+
return {
49+
catchedWarn: false
50+
}
51+
},
52+
beforeRouteEnter (to, from, next) {
53+
let missPropWarn = false
54+
Vue.config.silent = false
55+
Vue.config.warnHandler = function (msg, vm, trace) {
56+
if (/Missing required prop/i.test(msg)) {
57+
missPropWarn = true
58+
}
59+
}
60+
next(vm => {
61+
vm.catchedWarn = missPropWarn
62+
})
63+
},
64+
beforeRouteLeave (to, from, next) {
65+
// restore vue config
66+
Vue.config.silent = savedSilent
67+
Vue.config.warnHandler = savedWarnHandler
68+
next()
69+
}
70+
}
71+
3072
const router = new VueRouter({
3173
mode: 'history',
3274
base: __dirname,
@@ -58,6 +100,23 @@ const router = new VueRouter({
58100
path: '/with-guard2',
59101
name: 'with-guard2',
60102
component: WithGuard
103+
},
104+
{
105+
path: '/config-required-props',
106+
component: Parent,
107+
children: [
108+
{
109+
path: 'child',
110+
component: RequiredProps,
111+
props: {
112+
msg: 'ok'
113+
}
114+
}
115+
]
116+
},
117+
{
118+
path: '/catch-warn',
119+
component: CatchWarn
61120
}
62121
]
63122
})
@@ -72,6 +131,8 @@ new Vue({
72131
<li><router-link to="/home">/home</router-link></li>
73132
<li><router-link to="/with-guard1">/with-guard1</router-link></li>
74133
<li><router-link to="/with-guard2">/with-guard2</router-link></li>
134+
<li><router-link to="/config-required-props/child">/config-required-props/child</router-link></li>
135+
<li><router-link to="/catch-warn">/catch-warn</router-link></li>
75136
</ul>
76137
<keep-alive>
77138
<router-view class="view"></router-view>

src/components/view.js

+45-17
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,32 @@ export default {
4141

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

4759
const matched = route.matched[depth]
48-
// render empty node if no matched route
49-
if (!matched) {
60+
const component = matched && matched.components[name]
61+
62+
// render empty node if no matched route or no config component
63+
if (!matched || !component) {
5064
cache[name] = null
5165
return h()
5266
}
5367

54-
const component = cache[name] = matched.components[name]
68+
// cache component
69+
cache[name] = { component }
5570

5671
// attach instance registration hook
5772
// this will be called in the instance's injected lifecycle hooks
@@ -83,25 +98,38 @@ export default {
8398
}
8499
}
85100

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

101112
return h(component, data, children)
102113
}
103114
}
104115

116+
function passProps (component, data, route, configProps) {
117+
// resolve props
118+
let propsToPass = data.props = resolveProps(route, configProps)
119+
if (propsToPass) {
120+
// clone to prevent mutation
121+
propsToPass = data.props = extend({}, propsToPass)
122+
// pass non-declared props as attrs
123+
const attrs = data.attrs = data.attrs || {}
124+
for (const key in propsToPass) {
125+
if (!component.props || !(key in component.props)) {
126+
attrs[key] = propsToPass[key]
127+
delete propsToPass[key]
128+
}
129+
}
130+
}
131+
}
132+
105133
function resolveProps (route, config) {
106134
switch (typeof config) {
107135
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', 5)
12+
.assert.count('li a', 7)
1313

1414
.click('li:nth-child(1) a')
1515
.assert.containsText('.view', 'index child1')
@@ -35,6 +35,15 @@ module.exports = {
3535
.click('li:nth-child(4) a')
3636
.assert.containsText('.view', 'with-guard1: 3')
3737

38+
// missing props in nested routes with keep alive
39+
// https://github.com/vuejs/vue-router/issues/2301
40+
.click('li:nth-child(6) a')
41+
.assert.containsText('.view', 'props from route config is: ok')
42+
.click('li:nth-child(7) a')
43+
.assert.containsText('.view', 'no missing prop warn')
44+
.click('li:nth-child(6) a')
45+
.assert.containsText('.view', 'props from route config is: ok')
46+
3847
.end()
3948
}
4049
}

0 commit comments

Comments
 (0)