Skip to content

Commit

Permalink
feat(view): add props option as boolean
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Mar 15, 2020
1 parent 8ddc9b4 commit 7fe1e7d
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 9 deletions.
53 changes: 50 additions & 3 deletions __tests__/RouterView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ import { components, RouteLocationNormalizedLoose } from './utils'
import { START_LOCATION_NORMALIZED } from '../src/types'
import { ref, markNonReactive } from 'vue'
import { mount, tick } from './mount'
import { mockWarn } from 'jest-mock-warn'

const routes: Record<string, RouteLocationNormalizedLoose> = {
// to have autocompletion
function createRoutes<T extends Record<string, RouteLocationNormalizedLoose>>(
routes: T
): T {
return routes
}

const routes = createRoutes({
root: {
fullPath: '/',
name: undefined,
Expand Down Expand Up @@ -65,12 +73,30 @@ const routes: Record<string, RouteLocationNormalizedLoose> = {
meta: {},
matched: [{ components: { foo: components.Foo }, path: '/' }],
},
}
withParams: {
fullPath: '/users/3',
name: undefined,
path: '/users/3',
query: {},
params: { id: '1' },
hash: '',
meta: {},
matched: [
{
components: { default: components.User },
path: '/users/:id',
props: true,
},
],
},
})

describe('RouterView', () => {
mockWarn()

function factory(route: RouteLocationNormalizedLoose, props: any = {}) {
const router = {
currentRoute: ref(markNonReactive(route)),
currentRoute: ref(markNonReactive({ ...route })),
}

const { app, el } = mount(
Expand Down Expand Up @@ -104,6 +130,7 @@ describe('RouterView', () => {
it('displays nothing when route is unmatched', () => {
const { el } = factory(START_LOCATION_NORMALIZED as any)
// NOTE: I wonder if this will stay stable in future releases
expect('Router').not.toHaveBeenWarned()
expect(el.childElementCount).toBe(0)
})

Expand All @@ -126,4 +153,24 @@ describe('RouterView', () => {
await tick()
expect(el.innerHTML).toBe(`<div>Foo</div>`)
})

it('does not pass params as props by default', async () => {
let noPropsWithParams = {
...routes.withParams,
matched: [{ ...routes.withParams.matched[0], props: false }],
}
const { el, router } = factory(noPropsWithParams)
expect(el.innerHTML).toBe(`<div>User: default</div>`)
router.currentRoute.value = { ...noPropsWithParams, params: { id: '4' } }
await tick()
expect(el.innerHTML).toBe(`<div>User: default</div>`)
})

it('passes params as props with props: true', async () => {
const { el, router } = factory(routes.withParams)
expect(el.innerHTML).toBe(`<div>User: 1</div>`)
router.currentRoute.value = { ...routes.withParams, params: { id: '4' } }
await tick()
expect(el.innerHTML).toBe(`<div>User: 4</div>`)
})
})
14 changes: 13 additions & 1 deletion __tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
RouteRecordMultipleViews,
MatcherLocationNormalized,
RouteLocationNormalized,
RouteRecordCommon,
} from '../src/types'
import { h, resolveComponent } from 'vue'
import { h, resolveComponent, defineComponent } from 'vue'

export const tick = (time?: number) =>
new Promise(resolve => {
Expand All @@ -22,6 +23,7 @@ export interface RouteRecordViewLoose
'path' | 'name' | 'components' | 'children' | 'meta' | 'beforeEnter'
> {
leaveGuards?: any
props?: RouteRecordCommon['props']
aliasOf: RouteRecordViewLoose | undefined
}

Expand Down Expand Up @@ -83,6 +85,16 @@ export const components = {
Home: { render: () => h('div', {}, 'Home') },
Foo: { render: () => h('div', {}, 'Foo') },
Bar: { render: () => h('div', {}, 'Bar') },
User: defineComponent({
props: {
id: {
default: 'default',
},
},
render() {
return h('div', {}, 'User: ' + this.id)
},
}),
Nested: {
render: () => {
const RouterView = resolveComponent('RouterView')
Expand Down
8 changes: 7 additions & 1 deletion src/components/View.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@ export const View = defineComponent({
() => matchedRoute.value && matchedRoute.value.components[props.name]
)

const propsData = computed(() => {
if (!matchedRoute.value.props) return {}

return route.value.params
})

provide(matchedRouteKey, matchedRoute)

return () => {
return ViewComponent.value
? h(ViewComponent.value as any, { ...attrs })
? h(ViewComponent.value as any, { ...propsData.value, ...attrs })
: null
}
},
Expand Down
1 change: 1 addition & 0 deletions src/matcher/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export function normalizeRouteRecord(
children: (record as any).children || [],
name: record.name,
beforeEnter,
props: record.props || false,
meta: record.meta || {},
leaveGuards: [],
aliasOf: undefined,
Expand Down
7 changes: 6 additions & 1 deletion src/matcher/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { RouteRecordMultipleViews, NavigationGuard } from '../types'
import {
RouteRecordMultipleViews,
NavigationGuard,
RouteRecordCommon,
} from '../types'

// normalize component/components into components and make every property always present
export interface RouteRecordNormalized {
Expand All @@ -7,6 +11,7 @@ export interface RouteRecordNormalized {
components: RouteRecordMultipleViews['components']
children: Exclude<RouteRecordMultipleViews['children'], void>
meta: Exclude<RouteRecordMultipleViews['meta'], void>
props: Exclude<RouteRecordCommon['props'], void>
beforeEnter: RouteRecordMultipleViews['beforeEnter']
leaveGuards: NavigationGuard[]
aliasOf: RouteRecordNormalized | undefined
Expand Down
8 changes: 5 additions & 3 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export interface RouteRecordCommon {
path: string
alias?: string | string[]
name?: string
props?: boolean
// TODO: beforeEnter has no effect with redirect, move and test
beforeEnter?: NavigationGuard | NavigationGuard[]
meta?: Record<string | number | symbol, any>
Expand Down Expand Up @@ -166,9 +167,10 @@ export const START_LOCATION_NORMALIZED: RouteLocationNormalized = markNonReactiv
)

// make matched non enumerable for easy printing
Object.defineProperty(START_LOCATION_NORMALIZED, 'matched', {
enumerable: false,
})
// NOTE: commented for tests at RouterView.spec
// Object.defineProperty(START_LOCATION_NORMALIZED, 'matched', {
// enumerable: false,
// })

// Matcher types
// the matcher doesn't care about query and hash
Expand Down

0 comments on commit 7fe1e7d

Please sign in to comment.