]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(view): add props option as boolean
authorEduardo San Martin Morote <posva13@gmail.com>
Sun, 15 Mar 2020 23:13:23 +0000 (00:13 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Sun, 15 Mar 2020 23:13:23 +0000 (00:13 +0100)
__tests__/RouterView.spec.ts
__tests__/utils.ts
src/components/View.ts
src/matcher/index.ts
src/matcher/types.ts
src/types/index.ts

index b88b57c06ea9a889a41f584ee3a9b7e45428ddc4..17dd39f778accf88df7227337780c426b837079f 100644 (file)
@@ -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,
@@ -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(
@@ -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)
   })
 
@@ -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>`)
+  })
 })
index 1b88eeb52b5ecc731fe7216739269798060a6313..0a0b718c1d8c5865d395c2fa8e717be411cf85d6 100644 (file)
@@ -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 => {
@@ -22,6 +23,7 @@ export interface RouteRecordViewLoose
     'path' | 'name' | 'components' | 'children' | 'meta' | 'beforeEnter'
   > {
   leaveGuards?: any
+  props?: RouteRecordCommon['props']
   aliasOf: RouteRecordViewLoose | undefined
 }
 
@@ -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')
index 564f488bef823344c1111a62d7d465e764da279b..2016759c18a4eb6cbc763bf751bac655c74eb6d7 100644 (file)
@@ -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
     }
   },
index 1246aa92663044e20addc499ed34a263750e4490..4d919ca07bf9de05fd06682e6903545eae6d7a90 100644 (file)
@@ -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,
index d29c8423e89b9440ad194df407916e4370a4cb34..34153c368c60b2bb9ab6c2aafc3cd0c95cc11e48 100644 (file)
@@ -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 {
@@ -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
index 4c46b8881d8cf8a10e35265e1a0748151168810a..d9238df65077e34fd0f1ad25bfc9a7c23fb11127 100644 (file)
@@ -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>
@@ -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