]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor: migrate example to vue3
authorEduardo San Martin Morote <posva13@gmail.com>
Tue, 21 Jan 2020 16:46:12 +0000 (17:46 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Tue, 21 Jan 2020 16:46:12 +0000 (17:46 +0100)
21 files changed:
explorations/App.vue [new file with mode: 0644]
explorations/html5.html
explorations/html5.ts
explorations/router.ts [new file with mode: 0644]
explorations/scrollWaiter.ts [new file with mode: 0644]
explorations/shim.d.ts [new file with mode: 0644]
explorations/store.ts [new file with mode: 0644]
explorations/views/ComponentWithData.vue [new file with mode: 0644]
explorations/views/Generic.vue [new file with mode: 0644]
explorations/views/GuardedWithLeave.vue [new file with mode: 0644]
explorations/views/Home.vue [new file with mode: 0644]
explorations/views/LongView.vue [new file with mode: 0644]
explorations/views/NotFound.vue [new file with mode: 0644]
explorations/views/User.vue [new file with mode: 0644]
package.json
src/components/Link.ts
src/components/View.ts
src/index.ts
src/router.ts
webpack.config.js
yarn.lock

diff --git a/explorations/App.vue b/explorations/App.vue
new file mode 100644 (file)
index 0000000..6ad5e4b
--- /dev/null
@@ -0,0 +1,129 @@
+<template>
+  <div id="app">
+    <pre>{{ currentLocation }}</pre>
+    <section class="info">
+      Name:
+      <pre id="name">{{ currentLocation.name }}</pre>
+    </section>
+
+    <section class="info">
+      Params:
+      <pre id="params">{{ currentLocation.params }}</pre>
+    </section>
+
+    <section class="info">
+      Query:
+      <pre id="query">{{ currentLocation.query }}</pre>
+    </section>
+
+    <section class="info">
+      Hash:
+      <pre id="hash">{{ currentLocation.hash }}</pre>
+    </section>
+
+    <section class="info">
+      FullPath:
+      <pre id="fullPath">{{ currentLocation.fullPath }}</pre>
+    </section>
+
+    <section class="info">
+      path:
+      <pre id="path">{{ currentLocation.path }}</pre>
+    </section>
+
+    <hr />
+
+    <label>
+      <input type="checkbox" v-model="state.cancelNextNavigation" /> Cancel Next
+      Navigation
+    </label>
+    <ul>
+      <li>
+        <router-link to="/n/%E2%82%AC">/n/%E2%82%AC</router-link>
+      </li>
+      <li>
+        <router-link :to="{ name: 'docs', params: { id: '€uro' } }"
+          >/docs/€uro (object)</router-link
+        >
+      </li>
+      <li>
+        <router-link :to="{ name: 'home', query: { currency: '€uro', é: 'e' } }"
+          >/currency=€uro&é=e (object)</router-link
+        >
+      </li>
+      <li>
+        <router-link to="/documents/€">/n/€</router-link>
+      </li>
+      <li>
+        <a href="/documents/%E2%82%AC">/documents/%E2%82%AC (force reload)</a>
+      </li>
+      <li>
+        <a href="/documents/€">/documents/€ (force reload): not valid tho</a>
+      </li>
+      <li>
+        <router-link to="/">/</router-link>
+      </li>
+      <li>
+        <router-link to="/long-0">/long-0</router-link>
+      </li>
+      <li>
+        <router-link to="/users/5">/users/5</router-link>
+      </li>
+      <li>
+        <router-link
+          :to="{
+            name: 'user',
+            params: { id: Number(currentLocation.params.id || 0) + 1 },
+          }"
+          >/users/{{ Number(currentLocation.params.id || 0) + 1 }}</router-link
+        >
+      </li>
+      <!-- <li>
+          <router-link :to="{ name: 'docs' }">Doc with same id</router-link>
+        </li> -->
+      <li>
+        <router-link to="/with-data">/with-data</router-link>
+      </li>
+    </ul>
+    <transition
+      name="fade"
+      mode="out-in"
+      @before-enter="flushWaiter"
+      @before-leave="setupWaiter"
+    >
+      <router-view></router-view>
+    </transition>
+  </div>
+</template>
+
+<script>
+import { defineComponent, inject, computed } from 'vue'
+import { scrollWaiter } from './scrollWaiter'
+
+export default defineComponent({
+  name: 'App',
+  setup() {
+    const router = inject('router')
+    const state = inject('state')
+    const currentLocation = computed(() => {
+      const { matched, ...rest } = router.currentRoute.value
+      return rest
+    })
+
+    function flushWaiter() {
+      scrollWaiter.flush()
+    }
+    function setupWaiter() {
+      scrollWaiter.add()
+    }
+
+    const nextUserLink = computed(
+      () =>
+        '/users/' +
+        String((Number(router.currentRoute.value.params.id) || 0) + 1)
+    )
+
+    return { currentLocation, nextUserLink, state, flushWaiter, setupWaiter }
+  },
+})
+</script>
index e74fde52ca5e0bbee5d0eeb2c2f281796621b78f..058156a11defec784cc849c03d7767d85c88f049 100644 (file)
     </style>
   </head>
   <body>
-    <div id="app">
-      <pre>{{ currentLocation }}</pre>
-      <section class="info">
-        Name:
-        <pre id="name">{{ currentLocation.name }}</pre>
-      </section>
-
-      <section class="info">
-        Params:
-        <pre id="params">{{ currentLocation.params }}</pre>
-      </section>
-
-      <section class="info">
-        Query:
-        <pre id="query">{{ currentLocation.query }}</pre>
-      </section>
-
-      <section class="info">
-        Hash:
-        <pre id="hash">{{ currentLocation.hash }}</pre>
-      </section>
-
-      <section class="info">
-        FullPath:
-        <pre id="fullPath">{{ currentLocation.fullPath }}</pre>
-      </section>
-
-      <section class="info">
-        path:
-        <pre id="path">{{ currentLocation.path }}</pre>
-      </section>
-
-      <hr />
-
-      <label>
-        <input type="checkbox" v-model="state.cancelNextNavigation" /> Cancel
-        Next Navigation
-      </label>
-      <ul>
-        <li>
-          <router-link to="/n/%E2%82%AC">/n/%E2%82%AC</router-link>
-        </li>
-        <li>
-          <router-link :to="{ name: 'docs', params: { id: '€uro' }}"
-            >/docs/€uro (object)</router-link
-          >
-        </li>
-        <li>
-          <router-link
-            :to="{ name: 'home', query: { currency: '€uro', 'é': 'e' }}"
-            >/currency=€uro&é=e (object)</router-link
-          >
-        </li>
-        <li>
-          <router-link to="/documents/€">/n/€</router-link>
-        </li>
-        <li>
-          <a href="/documents/%E2%82%AC">/documents/%E2%82%AC (force reload)</a>
-        </li>
-        <li>
-          <a href="/documents/€">/documents/€ (force reload): not valid tho</a>
-        </li>
-        <li>
-          <router-link to="/">/</router-link>
-        </li>
-        <li>
-          <router-link to="/long-0">/long-0</router-link>
-        </li>
-        <li>
-          <router-link to="/users/5">/users/5</router-link>
-        </li>
-        <li>
-          <router-link
-            :to="{ name: 'user', params: { id: Number(currentLocation.params.id || 0) + 1 }}"
-            >/users/{{ Number(currentLocation.params.id || 0) + 1
-            }}</router-link
-          >
-        </li>
-        <!-- <li>
-          <router-link :to="{ name: 'docs' }">Doc with same id</router-link>
-        </li> -->
-        <li>
-          <router-link to="/with-data">/with-data</router-link>
-        </li>
-      </ul>
-      <transition
-        name="fade"
-        mode="out-in"
-        @before-enter="flushWaiter"
-        @before-leave="setupWaiter"
-      >
-        <router-view></router-view>
-      </transition>
-    </div>
+    <div id="app"></div>
   </body>
 </html>
index e7b80edbf3056c1713e5bea684c7ab67288d5c13..0cd262a9d7084a505e129529ea7c80e58ae6473c 100644 (file)
-import {
-  createRouter,
-  RouterPlugin,
-  // @ts-ignore
-  createHistory,
-  // @ts-ignore
-  createMemoryHistory,
-  // @ts-ignore
-  createHashHistory,
-  RouteLocationNormalized,
-} from '../src'
-import {
-  defineComponent,
-  computed,
-  createApp,
-  inject,
-  reactive,
-  Ref,
-} from 'vue'
+import { createApp } from 'vue'
+import { router, routerHistory } from './router'
+import { globalState } from './store'
+import { RouterPlugin } from '../src'
+import App from './App.vue'
 
 declare global {
   interface Window {
     // h: HTML5History
-    h: ReturnType<typeof createHistory>
-    r: ReturnType<typeof createRouter>
+    h: typeof routerHistory
+    r: typeof router
   }
 }
 
-// const routerHistory = createHistory('/app')
-// const routerHistory = createHashHistory()
-const routerHistory = createHistory()
+// for testing purposes
 window.h = routerHistory
-
-const component = defineComponent({
-  name: 'GenericComponent',
-  template: `<div>A component</div>`,
-})
-
-const NotFound = defineComponent({
-  name: 'NotFound',
-  setup() {
-    const route = inject('route')
-    return { route }
-  },
-  template: `<div>Not Found: {{ route.fullPath }}</div>`,
-})
-
-const Home = defineComponent({
-  name: 'Home',
-  template: `<div>Home</div>`,
-})
-
-const User = defineComponent({
-  name: 'User',
-  setup() {
-    const route = inject('route')
-    console.log({ route })
-    return { route }
-  },
-  template: `<div>User: {{ route.params.id }}</div>`,
-})
-
-const LongView = defineComponent({
-  name: 'LongView',
-  setup() {
-    const route = inject('route')
-    return { route }
-  },
-  template: `
-  <section>
-    <div class="long">This one is long: {{ route.params.n }}. Go down to click on a link</div>
-    <p class="long">
-      <router-link
-        :to="{ name: 'long', params: { n: Number(route.params.n || 0) + 1 }}"
-        >/long-{{ Number(route.params.n || 0) + 1 }}</router-link>
-    </p>
-  </section>
-  `,
-})
-
-const GuardedWithLeave = defineComponent({
-  name: 'GuardedWithLeave',
-  template: `<div>
-    <p>try to leave</p>
-  </div>`,
-  // @ts-ignore
-  beforeRouteLeave(to, from, next) {
-    if (window.confirm()) next()
-    else next(false)
-  },
-})
-
-const ComponentWithData = defineComponent({
-  name: 'ComponentWithData',
-  template: `<div>
-    <p>Here is the data: {{ data }}</p>
-  </div>`,
-  data: () => ({ data: 'nope' }),
-  // @ts-ignore
-  beforeRouteEnter(to, from, next) {
-    // console.log('this in beforeRouteEnter', this)
-    // setTimeout(() => {
-    // next(vm => {
-    //   // console.log('got vm', vm)
-    //   vm.data = 'Hola'
-    // })
-    // }, 300)
-  },
-})
+window.r = router
 
 if ('scrollRestoration' in history) {
   history.scrollRestoration = 'manual'
 }
 
-class ScrollQueue {
-  private resolve: (() => void) | null = null
-  private promise: Promise<any> | null = null
-
-  add() {
-    this.promise = new Promise(resolve => {
-      this.resolve = resolve
-    })
-  }
-
-  flush() {
-    this.resolve && this.resolve()
-    this.resolve = null
-    this.promise = null
-  }
-
-  async wait() {
-    await this.promise
-  }
-}
-
-const scrollWaiter = new ScrollQueue()
-
-// const hist = new HTML5History()
-// const hist = new HashHistory()
-const router = createRouter({
-  history: routerHistory,
-  routes: [
-    { path: '/', component: Home, name: 'home', alias: '/home' },
-    { path: '/users/:id', name: 'user', component: User },
-    { path: '/documents/:id', name: 'docs', component: User },
-    { path: encodeURI('/n/€'), name: 'euro', component },
-    { path: '/n/:n', name: 'increment', component },
-    { path: '/multiple/:a/:b', name: 'multiple', component },
-    { path: '/long-:n', name: 'long', component: LongView },
-    {
-      path: '/with-guard/:n',
-      name: 'guarded',
-      component,
-      beforeEnter(to, from, next) {
-        if (to.params.n !== 'valid') next(false)
-        next()
-      },
-    },
-    { path: '/cant-leave', component: GuardedWithLeave },
-    {
-      path: '/children',
-      component,
-      children: [
-        { path: '', name: 'default-child', component },
-        { path: 'a', name: 'a-child', component },
-        { path: 'b', name: 'b-child', component },
-      ],
-    },
-    { path: '/with-data', component: ComponentWithData, name: 'WithData' },
-    { path: '/rep/:a*', component: component, name: 'repeat' },
-    { path: '/:data(.*)', component: NotFound, name: 'NotFound' },
-  ],
-  async scrollBehavior(to, from, savedPosition) {
-    await scrollWaiter.wait()
-    if (savedPosition) {
-      return savedPosition
-    } else {
-      return { x: 0, y: 0 }
-    }
-  },
-})
-
-// for testing purposes
-window.r = router
-
-const delay = (t: number) => new Promise(resolve => setTimeout(resolve, t))
-
-router.beforeEach(async (to, from, next) => {
-  // console.log(`Guard from ${from.fullPath} to ${to.fullPath}`)
-  if (to.params.id === 'no-name') return next(false)
-
-  const time = Number(to.query.delay)
-  if (time > 0) {
-    console.log('⏳ waiting ' + time + 'ms')
-    await delay(time)
-  }
-  next()
-})
-
-router.beforeEach((to, from, next) => {
-  if (globalState.cancelNextNavigation) return next(false)
-  next()
-})
-
-router.afterEach((to, from) => {
-  // console.log(
-  //   `After guard: from ${from.fullPath} to ${
-  //     to.fullPath
-  //   } | location = ${location.href.replace(location.origin, '')}`
-  // )
-})
-
-router.beforeEach((to, from, next) => {
-  // console.log('second guard')
-  if (to.query.to) next(to.query.to as string)
-  else next()
-})
-
-const dirLog = {
-  '': '?',
-  back: '⏪',
-  forward: '⏩',
-}
-routerHistory.listen((to, from, info) => {
-  console.log(`${dirLog[info.direction]} as a ${info.type}`)
-})
-
-async function run() {
-  // router.push('/multiple/one/two')
-  // h.push('/hey')
-  // h.push('/hey?lol')
-  // h.push('/foo')
-  // h.push('/replace-me')
-  // h.replace('/bar')
-  // router.push('/about')
-  // await router.push('/')
-  // await router.push({
-  //   name: 'user',
-  //   params: {
-  //     id: '6',
-  //   },
-  // })
-  // await router.push({
-  //   name: 'user',
-  //   params: {
-  //     id: '5',
-  //   },
-  // })
-  // try {
-  //   await router.push({
-  //     params: {
-  //       id: 'no-name',
-  //     },
-  //   })
-  // } catch (err) {
-  //   console.log('Navigation aborted', err)
-  // }
-  // await router.push({
-  //   hash: '#hey',
-  // })
-  // await router.push('/children')
-  // await router.push('/children/a')
-  // await router.push('/children/b')
-  // await router.push({ name: 'a-child' })
-}
-
-const globalState = reactive({
-  cancelNextNavigation: false,
-})
-
-const App = defineComponent({
-  name: 'App',
-  setup() {
-    // TODO: should be a computed property or a readonly ref
-    const route = inject<Ref<RouteLocationNormalized>>('route')!
-    const state = inject<typeof globalState>('state')!
-    const currentLocation = computed(() => {
-      const { matched, ...rest } = route.value
-      return rest
-    })
-
-    function flushWaiter() {
-      scrollWaiter.flush()
-    }
-    function setupWaiter() {
-      scrollWaiter.add()
-    }
-
-    const nextUserLink = computed(
-      () =>
-        '/users/' +
-        String((Number(router.currentRoute.value.params.id) || 0) + 1)
-    )
-
-    return { currentLocation, nextUserLink, state, flushWaiter, setupWaiter }
-  },
-  template: document.getElementById('app')?.innerHTML,
-})
-
 const app = createApp()
 app.provide('state', globalState)
 app.use(RouterPlugin, router)
 
 app.mount(App, '#app')
-
-// use the router
-// Vue.use(plugin)
-
-// window.vm = new Vue({
-// el: '#app',
-// @ts-ignore
-// router,
-// data: {
-//   message: 'hello',
-//   shared,
-// },
-
-// methods: {
-
-// try out watchers
-// watch: {
-//   'route.params.id' (id) {
-//     console.log('id changed', id)
-//   },
-//   'route.name' (name) {
-//     console.log('name changed', name)
-//   }
-// }
-// })
-
-run()
diff --git a/explorations/router.ts b/explorations/router.ts
new file mode 100644 (file)
index 0000000..a136bf8
--- /dev/null
@@ -0,0 +1,98 @@
+import { createRouter, createHistory } from '../src'
+import Home from './views/Home.vue'
+import User from './views/User.vue'
+import NotFound from './views/NotFound.vue'
+import component from './views/Generic.vue'
+import LongView from './views/LongView.vue'
+import GuardedWithLeave from './views/GuardedWithLeave.vue'
+import ComponentWithData from './views/ComponentWithData.vue'
+import { globalState } from './store'
+import { scrollWaiter } from './scrollWaiter'
+
+// const hist = new HTML5History()
+// const hist = new HashHistory()
+export const routerHistory = createHistory()
+export const router = createRouter({
+  history: routerHistory,
+  routes: [
+    { path: '/', component: Home, name: 'home', alias: '/home' },
+    { path: '/users/:id', name: 'user', component: User },
+    { path: '/documents/:id', name: 'docs', component: User },
+    { path: encodeURI('/n/€'), name: 'euro', component },
+    { path: '/n/:n', name: 'increment', component },
+    { path: '/multiple/:a/:b', name: 'multiple', component },
+    { path: '/long-:n', name: 'long', component: LongView },
+    {
+      path: '/with-guard/:n',
+      name: 'guarded',
+      component,
+      beforeEnter(to, from, next) {
+        if (to.params.n !== 'valid') next(false)
+        next()
+      },
+    },
+    { path: '/cant-leave', component: GuardedWithLeave },
+    {
+      path: '/children',
+      component,
+      children: [
+        { path: '', name: 'default-child', component },
+        { path: 'a', name: 'a-child', component },
+        { path: 'b', name: 'b-child', component },
+      ],
+    },
+    { path: '/with-data', component: ComponentWithData, name: 'WithData' },
+    { path: '/rep/:a*', component: component, name: 'repeat' },
+    { path: '/:data(.*)', component: NotFound, name: 'NotFound' },
+  ],
+  async scrollBehavior(to, from, savedPosition) {
+    await scrollWaiter.wait()
+    if (savedPosition) {
+      return savedPosition
+    } else {
+      return { x: 0, y: 0 }
+    }
+  },
+})
+
+const delay = (t: number) => new Promise(resolve => setTimeout(resolve, t))
+
+router.beforeEach(async (to, from, next) => {
+  // console.log(`Guard from ${from.fullPath} to ${to.fullPath}`)
+  if (to.params.id === 'no-name') return next(false)
+
+  const time = Number(to.query.delay)
+  if (time > 0) {
+    console.log('⏳ waiting ' + time + 'ms')
+    await delay(time)
+  }
+  next()
+})
+
+router.beforeEach((to, from, next) => {
+  if (globalState.cancelNextNavigation) return next(false)
+  next()
+})
+
+router.afterEach((to, from) => {
+  // console.log(
+  //   `After guard: from ${from.fullPath} to ${
+  //     to.fullPath
+  //   } | location = ${location.href.replace(location.origin, '')}`
+  // )
+})
+
+router.beforeEach((to, from, next) => {
+  // console.log('second guard')
+  if (to.query.to) next(to.query.to as string)
+  else next()
+})
+
+const dirLog = {
+  '': '?',
+  back: '⏪',
+  forward: '⏩',
+}
+routerHistory.listen((to, from, info) => {
+  console.log(`${dirLog[info.direction]} as a ${info.type}`)
+})
diff --git a/explorations/scrollWaiter.ts b/explorations/scrollWaiter.ts
new file mode 100644 (file)
index 0000000..48e237b
--- /dev/null
@@ -0,0 +1,22 @@
+class ScrollQueue {
+  private resolve: (() => void) | null = null
+  private promise: Promise<any> | null = null
+
+  add() {
+    this.promise = new Promise(resolve => {
+      this.resolve = resolve
+    })
+  }
+
+  flush() {
+    this.resolve && this.resolve()
+    this.resolve = null
+    this.promise = null
+  }
+
+  async wait() {
+    await this.promise
+  }
+}
+
+export const scrollWaiter = new ScrollQueue()
diff --git a/explorations/shim.d.ts b/explorations/shim.d.ts
new file mode 100644 (file)
index 0000000..996ea4d
--- /dev/null
@@ -0,0 +1,5 @@
+declare module '*.vue' {
+  import { Component } from 'vue'
+  var component: Component
+  export default component
+}
diff --git a/explorations/store.ts b/explorations/store.ts
new file mode 100644 (file)
index 0000000..54e2228
--- /dev/null
@@ -0,0 +1,5 @@
+import { reactive } from 'vue'
+
+export const globalState = reactive({
+  cancelNextNavigation: false,
+})
diff --git a/explorations/views/ComponentWithData.vue b/explorations/views/ComponentWithData.vue
new file mode 100644 (file)
index 0000000..0d32d83
--- /dev/null
@@ -0,0 +1,23 @@
+<template>
+  <div>
+    <p>Here is the data: {{ data }}</p>
+  </div>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'ComponentWithData',
+  data: () => ({ data: 'nope' }),
+  beforeRouteEnter(to, from, next) {
+    // console.log('this in beforeRouteEnter', this)
+    // setTimeout(() => {
+    // next(vm => {
+    //   // console.log('got vm', vm)
+    //   vm.data = 'Hola'
+    // })
+    // }, 300)
+  },
+})
+</script>
diff --git a/explorations/views/Generic.vue b/explorations/views/Generic.vue
new file mode 100644 (file)
index 0000000..8079c80
--- /dev/null
@@ -0,0 +1,11 @@
+<template>
+  <div>Generic view</div>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'Generic',
+})
+</script>
diff --git a/explorations/views/GuardedWithLeave.vue b/explorations/views/GuardedWithLeave.vue
new file mode 100644 (file)
index 0000000..e4a65ec
--- /dev/null
@@ -0,0 +1,17 @@
+<template>
+  <div>
+    <p>try to leave</p>
+  </div>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'GuardedWithLeave',
+  beforeRouteLeave(to, from, next) {
+    if (window.confirm()) next()
+    else next(false)
+  },
+})
+</script>
diff --git a/explorations/views/Home.vue b/explorations/views/Home.vue
new file mode 100644 (file)
index 0000000..3e41c61
--- /dev/null
@@ -0,0 +1,11 @@
+<template>
+  <div>Home</div>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'Home',
+})
+</script>
diff --git a/explorations/views/LongView.vue b/explorations/views/LongView.vue
new file mode 100644 (file)
index 0000000..a1e06a7
--- /dev/null
@@ -0,0 +1,25 @@
+<template>
+  <section>
+    <div class="long">
+      This one is long: {{ route.params.n }}. Go down to click on a link
+    </div>
+    <p class="long">
+      <router-link
+        :to="{ name: 'long', params: { n: Number(route.params.n || 0) + 1 } }"
+        >/long-{{ Number(route.params.n || 0) + 1 }}</router-link
+      >
+    </p>
+  </section>
+</template>
+
+<script>
+import { defineComponent, inject } from 'vue'
+
+export default defineComponent({
+  name: 'LongView',
+  setup() {
+    const route = inject('route')
+    return { route }
+  },
+})
+</script>
diff --git a/explorations/views/NotFound.vue b/explorations/views/NotFound.vue
new file mode 100644 (file)
index 0000000..f999958
--- /dev/null
@@ -0,0 +1,15 @@
+<template>
+  <div>Not Found: {{ route.fullPath }}</div>
+</template>
+
+<script>
+import { defineComponent, inject } from 'vue'
+
+export default defineComponent({
+  name: 'NotFound',
+  setup() {
+    const route = inject('route')
+    return { route }
+  },
+})
+</script>
diff --git a/explorations/views/User.vue b/explorations/views/User.vue
new file mode 100644 (file)
index 0000000..fef21a8
--- /dev/null
@@ -0,0 +1,15 @@
+<template>
+  <div>User: {{ route.params.id }}</div>
+</template>
+
+<script>
+import { defineComponent, inject } from 'vue'
+
+export default defineComponent({
+  name: 'User',
+  setup() {
+    const route = inject('route')
+    return { route }
+  },
+})
+</script>
index c51ac3149f4c9683bfa588ce815432c2365715cb..3767c7d199de690cd880947d5294cfc18121e7b3 100644 (file)
@@ -26,6 +26,7 @@
     "@types/jsdom": "^12.2.4",
     "@types/webpack": "^4.41.2",
     "@types/webpack-env": "^1.15.0",
+    "@vue/compiler-sfc": "^3.0.0-alpha.2",
     "axios": "^0.19.1",
     "browserstack-local": "^1.4.4",
     "chromedriver": "^78.0.1",
@@ -52,6 +53,7 @@
     "ts-node": "^8.6.2",
     "typescript": "^3.7.4",
     "vue": "^3.0.0-alpha.2",
+    "vue-loader": "^16.0.0-alpha.2",
     "webpack": "^4.41.5",
     "webpack-cli": "^3.3.10",
     "webpack-dev-server": "^3.9.0"
index 7d04d7874ad4803ab0ebe5f7f7f53af8e5ef5437..b7dbc114e4097f14301a75c5790937ded33769fd 100644 (file)
@@ -1,4 +1,5 @@
-import { defineComponent, h, PropType, inject, computed } from 'vue'
+import { defineComponent, h, PropType, inject } from '@vue/runtime-core'
+import { computed } from '@vue/reactivity'
 import { Router } from '../router'
 import { RouteLocation } from '../types'
 
index a6b693963495a9d69b44cb7c59391e3d1245d607..5f36428afeef93bc6f6ac2ee68bd02d1058f15ae 100644 (file)
@@ -1,4 +1,4 @@
-import { h, inject, FunctionalComponent } from 'vue'
+import { h, FunctionalComponent, inject } from '@vue/runtime-core'
 import { Router } from '../'
 
 interface Props {
@@ -21,6 +21,7 @@ const View: FunctionalComponent<Props> = (props, { slots, attrs }) => {
   const component = matched.components[props.name || 'default']
 
   // TODO: remove any
+  // const children = typeof slots.default === 'function' ? slots.default() : []
   return h(component as any, attrs, slots.default)
 }
 
index 1a014115cbccbc4be9f5834ef8b8a2e246cd28c6..b89505f14fa96bcaeeb6e2681c15ad88532f5e9a 100644 (file)
@@ -1,5 +1,5 @@
 import { createRouter, Router } from './router'
-import { App } from 'vue'
+import { App } from '@vue/runtime-core'
 import createHistory from './history/html5'
 import createMemoryHistory from './history/memory'
 import createHashHistory from './history/hash'
index b9efe592b37a026d0e9c5daaa9da6a21620c1f40..6e7b869315897a6b8d52756a9442b7f3ec3066c5 100644 (file)
@@ -33,7 +33,7 @@ import {
 import { extractComponentsGuards, guardToPromiseFn } from './utils'
 import { encodeParam } from './utils/encoding'
 import { decode } from './utils/encoding'
-import { ref, Ref } from 'vue'
+import { ref, Ref } from '@vue/reactivity'
 
 type ErrorHandler = (error: any) => any
 // resolve, reject arguments of Promise constructor
index fd1dc5c5fcbe6732cfb2cd9c74d4cb6d03caf848..d79864974891a9bc286f17a39ed470edcac88abb 100644 (file)
@@ -1,5 +1,6 @@
 const { resolve } = require('path')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
+const { VueLoaderPlugin } = require('vue-loader')
 const webpack = require('webpack')
 
 const outputPath = resolve(__dirname, 'examples_dist')
@@ -25,16 +26,25 @@ module.exports = {
         test: /\.ts$/,
         use: 'ts-loader',
       },
+      {
+        test: /\.vue$/,
+        use: 'vue-loader',
+      },
     ],
   },
   resolve: {
     alias: {
-      vue: resolve(__dirname, './node_modules/vue/dist/vue.esm.js'),
+      // this isn't technically needed, since the default `vue` entry for bundlers
+      // is a simple `export * from '@vue/runtime-dom`. However having this
+      // extra re-export somehow causes webpack to always invalidate the module
+      // on the first HMR update and causes the page to reload.
+      vue: '@vue/runtime-dom',
     },
     // Add `.ts` and `.tsx` as a resolvable extension.
-    extensions: ['.ts', '.tsx', '.js'],
+    extensions: ['.ts', '.tsx', '.js', '.vue'],
   },
   plugins: [
+    new VueLoaderPlugin(),
     new HtmlWebpackPlugin({
       template: resolve(__dirname, 'explorations/html5.html'),
     }),
index 04e4a7a539711feae32e3d7becb17a5723413786..d9fc930b3d567a2d1d1ef293e864fd19de560296 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
   dependencies:
     "@vue/compiler-core" "3.0.0-alpha.2"
 
+"@vue/compiler-sfc@^3.0.0-alpha.2":
+  version "3.0.0-alpha.2"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.0-alpha.2.tgz#b8d7485c2075a107508a1554b75cc5058460ba0b"
+  integrity sha512-lOlGX8znccwrC8iLcw/dQt58xt0rR9D+Sj7SDiWcIXCrOWEIE5j1obGdJnOjuysnZKu9w80XtQY5E4zeCNhJWw==
+  dependencies:
+    "@vue/compiler-core" "3.0.0-alpha.2"
+    "@vue/compiler-dom" "3.0.0-alpha.2"
+    consolidate "^0.15.1"
+    hash-sum "^2.0.0"
+    lru-cache "^5.1.1"
+    merge-source-map "^1.1.0"
+    postcss "^7.0.21"
+    postcss-selector-parser "^6.0.2"
+    source-map "^0.6.1"
+
 "@vue/reactivity@3.0.0-alpha.2":
   version "3.0.0-alpha.2"
   resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.0-alpha.2.tgz#8d0b235652f1834236325c36ea0ba419e06df423"
@@ -1107,7 +1122,7 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
   integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
 
-bluebird@^3.5.0, bluebird@^3.5.5:
+bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
@@ -1673,6 +1688,13 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
   integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
 
+consolidate@^0.15.1:
+  version "0.15.1"
+  resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
+  integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==
+  dependencies:
+    bluebird "^3.1.1"
+
 constants-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -3116,6 +3138,11 @@ hash-base@^3.0.0:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
+hash-sum@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
+  integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
+
 hash.js@^1.0.0, hash.js@^1.0.3:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
@@ -4641,6 +4668,13 @@ merge-descriptors@1.0.1:
   resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
   integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
 
+merge-source-map@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
+  integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
+  dependencies:
+    source-map "^0.6.1"
+
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -5671,6 +5705,15 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.
     source-map "^0.6.1"
     supports-color "^6.1.0"
 
+postcss@^7.0.21:
+  version "7.0.26"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587"
+  integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==
+  dependencies:
+    chalk "^2.4.2"
+    source-map "^0.6.1"
+    supports-color "^6.1.0"
+
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -7350,6 +7393,17 @@ vm-browserify@^1.0.1:
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
   integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
 
+vue-loader@^16.0.0-alpha.2:
+  version "16.0.0-alpha.2"
+  resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.0.0-alpha.2.tgz#461c4c1638115416233195f56ef4bc9ea96e2ad6"
+  integrity sha512-rDiLE1lH4g2JTZ6XQRVq60kDp0GnGhgqAaAC/dh7d5alIYw1Cy/VGTkT2SBqBLA1gXwqxX1dPiYz/jrXp2bxkA==
+  dependencies:
+    chalk "^3.0.0"
+    hash-sum "^2.0.0"
+    loader-utils "^1.2.3"
+    merge-source-map "^1.1.0"
+    source-map "^0.6.1"
+
 vue@^3.0.0-alpha.2:
   version "3.0.0-alpha.2"
   resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-alpha.2.tgz#98e1769e264110404e7131a4258f23ba554a885b"