8000 fix(router-view): add passing props to inactive component by zrh122 · Pull Request #2773 · vuejs/vue-router · GitHub
[go: up one dir, main page]

Skip to content

fix(router-view): add passing props to inactive component #2773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(router-view): add passing props to inactive component
  • Loading branch information
zrh122 committed Jan 14, 2020
commit b2429abde2fec36eb28b8d8efe89a4a1446f0457
61 changes: 61 additions & 0 deletions examples/keepalive-view/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,48 @@ const Home = { template: '<div>home</div>' }

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

const Parent = { template: '<router-view />' }

const RequiredProps = {
template: '<div>props from route config is: {{msg}}</div>',
props: {
msg: {
type: String,
required: true
}
}
}

const savedSilent = Vue.config.silent
const savedWarnHandler = Vue.config.warnHandler

const CatchWarn = {
template: `<div>{{catchedWarn ? 'catched missing prop warn' : 'no missing prop warn'}}</div>`,
data () {
return {
catchedWarn: false
}
},
beforeRouteEnter (to, from, next) {
let missPropWarn = false
Vue.config.silent = false
Vue.config.warnHandler = function (msg, vm, trace) {
if (/Missing required prop/i.test(msg)) {
missPropWarn = true
}
}
next(vm => {
vm.catchedWarn = missPropWarn
})
},
beforeRouteLeave (to, from, next) {
// restore vue config
Vue.config.silent = savedSilent
Vue.config.warnHandler = savedWarnHandler
next()
}
}

const router = new VueRouter({
mode: 'history',
base: __dirname,
Expand Down Expand Up @@ -80,6 +122,23 @@ const router = new VueRouter({
]
}
]
},
{
path: '/config-required-props',
component: Parent,
children: [
{
path: 'child',
component: RequiredProps,
props: {
msg: 'ok'
}
}
]
},
{
path: '/catch-warn',
component: CatchWarn
}
]
})
Expand All @@ -96,6 +155,8 @@ new Vue({
<li><router-link to="/with-guard2">/with-guard2</router-link></li>
<li><router-link to="/one/two/child1">/one/two/child1</router-link></li>
<li><router-link to="/one/two/child2">/one/two/child2</router-link></li>
<li><router-link to="/config-required-props/child">/config-required-props/child</router-link></li>
<li><router-link to="/catch-warn">/catch-warn</router-link></li>
</ul>
<keep-alive>
<router-view class="view"></router-view>
Expand Down
62 changes: 45 additions & 17 deletions src/components/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,32 @@ export default {

// render previous view if the tree is inactive and kept-alive
if (inactive) {
return h(cache[name], data, children)
const cachedData = cache[name]
const cachedComponent = cachedData && cachedData.component
if (cachedComponent) {
// #2301
// pass props
if (cachedData.configProps) {
passProps(cachedComponent, data, cachedData.route, cachedData.configProps)
}
return h(cachedComponent, data, children)
} else {
// render previous empty view
return h()
}
}

const matched = route.matched[depth]
// render empty node if no matched route
if (!matched) {
const component = matched && matched.components[name]

// render empty node if no matched route or no config component
if (!matched || !component) {
cache[name] = null
return h()
}

const component = cache[name] = matched.components[name]
// cache component
cache[name] = { component }

// attach instance registration hook
// this will be called in the instance's injected lifecycle hooks
Expand Down Expand Up @@ -81,25 +96,38 @@ export default {
}
}

// resolve props
let propsToPass = data.props = resolveProps(route, matched.props && matched.props[name])
if (propsToPass) {
// clone to prevent mutation
propsToPass = data.props = extend({}, propsToPass)
// pass non-declared props as attrs
const attrs = data.attrs = data.attrs || {}
for (const key in propsToPass) {
if (!component.props || !(key in component.props)) {
attrs[key] = propsToPass[key]
delete propsToPass[key]
}
}
const configProps = matched.props && matched.props[name]
// pass props
if (configProps) {
// add route and config props to cache data
extend(cache[name], {
route,
configProps
})
passProps(component, data, route, configProps)
}

return h(component, data, children)
}
}

function passProps (component, data, route, configProps) {
// resolve props
let propsToPass = data.props = resolveProps(route, configProps)
if (propsToPass) {
// clone to prevent mutation
propsToPass = data.props = extend({}, propsToPass)
// pass non-declared props as attrs
const attrs = data.attrs = data.attrs || {}
for (const key in propsToPass) {
if (!component.props || !(key in component.props)) {
attrs[key] = propsToPass[key]
delete propsToPass[key]
}
}
}
}

function resolveProps (route, config) {
switch (typeof config) {
case 'undefined':
Expand Down
11 changes: 10 additions & 1 deletion test/e2e/specs/keepalive-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
browser
.url('http://localhost:8080/keepalive-view/')
.waitForElementVisible('#app', 1000)
.assert.count('li a', 7)
.assert.count('li a', 9)

.click('li:nth-child(1) a')
.assert.containsText('.view', 'index child1')
Expand Down Expand Up @@ -44,6 +44,15 @@ module.exports = {
.click('li:nth-child(7) a')
.assert.containsText('.view', 'index child2')

// missing props in nested routes with keep alive
// https://github.com/vuejs/vue-router/issues/2301
.click('li:nth-child(8) a')
.assert.containsText('.view', 'props from route config is: ok')
.click('li:nth-child(9) a')
.assert.containsText('.view', 'no missing prop warn')
.click('li:nth-child(8) a')
.assert.containsText('.view', 'props from route config is: ok')

.end()
}
}
0