]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(guards): wip context support in multi apps
authorEduardo San Martin Morote <posva13@gmail.com>
Tue, 21 Jul 2020 09:46:40 +0000 (11:46 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Tue, 21 Jul 2020 11:41:45 +0000 (13:41 +0200)
e2e/multi-app/index.ts
e2e/specs/multi-app.js
src/navigationGuards.ts

index a8431bc1a93a4741b8d2fe37528e138d823a71b5..3a975f327abd3600ef4a95e082e35337062051f6 100644 (file)
@@ -1,15 +1,60 @@
-import { createRouter, createWebHistory } from '../../src'
+import { createRouter, createWebHistory, onBeforeRouteUpdate } from '../../src'
 import { RouteComponent } from '../../src/types'
-import { createApp, ref, watchEffect, App } from 'vue'
+import { createApp, ref, watchEffect, App, inject } from 'vue'
 
 const Home: RouteComponent = {
   template: `<div class="home">Home</div>`,
 }
 
 const User: RouteComponent = {
-  template: `<div class="user">User {{ $route.params.id }}</div>`,
+  template: `<div class="user">User {{ $route.params.id }}. Updated <span class="count">{{ count }}</span></div>`,
+  data: () => ({ count: 0 }),
+
+  beforeRouteEnter(to, from, next) {
+    next(vm => {
+      // @ts-ignore
+      console.log('enter from ', vm.id)
+      // @ts-ignore
+    })
+  },
+
+  beforeRouteUpdate(to, from, next) {
+    // this.count++
+    next()
+  },
+
+  setup() {
+    const id = inject('id')!
+
+    if (id !== 1)
+      onBeforeRouteUpdate(function (to, from, next) {
+        // @ts-ignore
+        console.log('update from ', id, this.id)
+        // @ts-ignore
+        // this.count++
+        next()
+      })
+
+    return { id }
+  },
 }
 
+let looper = [1, 2, 3]
+
+const NamedViews: RouteComponent[] = looper.map(i => ({
+  name: 'part-' + i,
+
+  template: `<div class="named part-${i}">Part ${i}. Updated <span class="count">{{ count }}</span></div>`,
+
+  data: () => ({ count: 0 }),
+
+  beforeRouteUpdate(to, from, next) {
+    // @ts-ignore
+    // this.count++
+    next()
+  },
+}))
+
 // path popstate listeners to track the call count
 let activePopStateListeners = ref(0)
 let guardCallCount = ref(0)
@@ -43,7 +88,19 @@ const router = createRouter({
   history: createWebHistory('/' + __dirname),
   routes: [
     { path: '/', component: Home },
-    { path: '/users/:id', component: User },
+    {
+      path: '/users/:id',
+      components: {
+        default: User,
+        ...NamedViews.reduce(
+          (routeComponents, component) => ({
+            ...routeComponents,
+            [component.name!]: component,
+          }),
+          {} as Record<string, RouteComponent>
+        ),
+      },
+    },
   ],
 })
 
@@ -52,8 +109,6 @@ router.beforeEach((to, from, next) => {
   next()
 })
 
-let looper = [1, 2, 3]
-
 let apps: Array<App | null> = [null, null, null]
 
 looper.forEach((n, i) => {
@@ -71,10 +126,12 @@ looper.forEach((n, i) => {
       </ul>
 
       <router-view></router-view>
+      <router-view name="part-${n}"></router-view>
     </div>
   `,
     }))
     app.use(router)
+    app.provide('id', n)
     app.mount('#app-' + n)
   })
 
index 07fe895751304ca8995990d7664927a4c20cebac..97b94f2d1b8ea99824478eb75835a9ae4d29facc 100644 (file)
@@ -97,4 +97,28 @@ module.exports = {
 
       .end()
   },
+
+  /** @type {import('nightwatch').NightwatchTest} */
+  'supports navigation guards context with multiple apps': function (browser) {
+    browser
+      .url(baseURL)
+      .assert.urlEquals(baseURL + '/')
+
+      // mount multiple apps and expect to have one listener only
+      .click('#mount1')
+      .assert.containsText('#app-1 .home', 'Home')
+      // toggle multiple times
+      .click('#app-1 li:nth-child(2) a')
+      .assert.containsText('#app-1 .count', '0')
+      .click('#app-1 li:nth-child(3) a')
+      .assert.containsText('#app-1 .count', '1')
+      .click('#mount2')
+      .assert.containsText('#app-2 .user', 'User 2')
+      .click('#app-1 li:nth-child(2) a')
+      // first one keeps updating
+      .assert.containsText('#app-1 .count', '2')
+      // second app only updated once
+      .assert.containsText('#app-2 .count', '1')
+      .click('#mount3')
+  },
 }
index 53bee1046c320ae9e33002c83a8bb90358ac0cd6..d1d61f34d4186804177dee347f4cdba96ab3d822 100644 (file)
@@ -260,3 +260,16 @@ function isRouteComponent(
     '__vccOpts' in component
   )
 }
+
+/**
+ * 1. beforeRouteEnter callbacks
+ * 2. Dictionary of instances per view name
+ */
+export type GuardManagerEntry = [
+  NavigationGuardNextCallback[],
+  Record<string, ComponentPublicInstance | undefined | null>
+]
+
+export function createGuardManager() {
+  return new Map<RouteRecordNormalized, GuardManagerEntry>()
+}