• 开始时间:2020-02-20
  • 目标主要版本:Vue Router 4.x
  • 引用 issue:N/A
  • 实现的 PR:N/A

摘要

鉴于 Vue3 中函数式组件的变化,KeepAlive 和 Transition 的使用与 RouterView 的结合不再是简单的用 KeepAlive/Transition 来包装 RouterView 就可以实现的。相反,我们需要一种方法来直接向这些组件提供由 RouterView 渲染的组件:

  1. <router-view v-slot="{ Component }">
  2. <transition :name="transitionName" mode="out-in">
  3. <component :is="Component"></component>
  4. </transition>
  5. </router-view>

基本范例

N/A

动机

正如在 https://github.com/vuejs/vue-next/issues/906#issuecomment-611080663,我们需要一个新的 API 来允许 KeepAlive 和其他接受插槽的 RouterView 的组件。为了实现这样的行为,我们需要能够直接包装 RouterView 所渲染的组件和传递给它的属性。

具体设计

我们可以通过一个插槽实现这种控制的水平:

  1. <router-view v-slot="{ Component, route }">
  2. <component :is="Component" v-bind="route.params"></component>
  3. </router-view>

在这个例子中,Component 是组件的定义,可以传递给函数 h 或组件的 is 属性。
当在路由定义中定义一个 props: true 选项时:

没有匹配的例子

当当前的位置没有被 Router 注册的任何记录所匹配时,RouterLocationmatched 数组是空的,默认情况下,当没有插槽时,它不会渲染任何内容。当我们提供一个插槽时,我们可以决定显示什么,无论我们想显示一个未找到的页面,还是我们想要的默认行为,我们都可以做到这一点。如果没有组件需要渲染,Component 将是假的:

  1. <router-view v-slot="{ Component, route }">
  2. <component v-if="route.matched.length > 0" :is="Component"/>
  3. <div v-else>Not Found</div>
  4. </router-view>

请注意,在显示未找到的页面时,这种行为与 catch all 路由(path: '/:pathMatch(.*)‘)是多余的。

v-slot 属性

  • Component:可以传递给函数 hcomponentis 属性的组件
  • route:由 RouterView 渲染的规范化 Route 位置。与 $route 相同,但允许在 JSX 中简单和类型化的访问。

TransitionKeepAlive 包装 RouterView

如果用户不小心用 Transition 包装了 RouterView,或者正在将他们的应用程序迁移到 Vue3,我们可以发出一个警告,志向文档(同时时这个 RFC)并提示他们使用 v-slot api。

同时使用 KeepAliveTransition

当同时使用 KeepAliveTransition 时,我们需要先用 Transition 再用 KeepAlive

  1. <router-view v-slot="{ Component }">
  2. <transition name="fade" mode="out-in">
  3. <keep-alive>
  4. <component :is="Component"></component>
  5. </keep-alive>
  6. </transition>
  7. </router-view>

缺点

N/A

备选方案

  • 使用像 useView 这样的函数,将返回 Componentattrs,删除 v-slot 的使用。

采纳策略

  • codemod 可以将 v3 重写成 v4

没有解决的问题

N/A