vue-router单页面应用的多标签页使用问题

正常的思维

做多vue页面应用,我们的第一反应是配置多个入口点,多个vue应用,编译成多个HTML文件,由服务器来决定路由。这是正常的思维。
但谁知道单页面应用也能做到类似的效果呢。单页面不过是服务器路由变成了客户端路由,但通过一些技巧,也能实现类似服务器多页面路由的效果。

客户端路由多页面的实现方式

我以vue-router举例

多个根路由

最简单的多页面应用,是设置多个根路由。这样在新标签页打开不同的根路由,就相当于多页面应用。
只是实际上,这些不同的标签页还是同一个vue应用。不过是呈现了不同的组件罢了,网络请求的js资源还是一样。
比如这种

const router = new VueRouter({
  routes: [
    {
      path: '/parent',
      component: ParentComponent,
    },
    {
      path: 'standalone-child',
      component: ChildComponent
    }
  ]
})

可以在两个标签页打开,http://5234/#/parenthttp://5234/#/standalone-child。两个组件的内容互不干扰。
image
image

看起来客户端路由是利用锚点实现的。
但这无法解决嵌套路由的问题,
比如

const router = new VueRouter({
  routes: [
    {
      path: '/parent',
      component: ParentComponent,
      children: [
        {
          path: 'child',
          component: ChildComponent
        }
      ]
    },
    {
      path: '/standalone-child',
      component: ChildComponent
    }
  ]
});

我们访问http://5234/#/parent/child居然会把http://5234/#/parent路由的ParentComponent组件的内容显示出来。
ChildComponent看起来似乎就像一个iframe一样呢。
image

虽然有时也需要这种效果,但有时也需要这个“iframe”独立显示。我们需要这种控制权。

条件渲染与查询参数

第二种方式是条件渲染与查询参数。在router配置中使用路由参数+ParentComponent组件中使用条件渲染

  • 首先在路由配置中增加路由参数:standalone
const routes = [
    {
        path: '/',
        component: App,
    },
    {
        path: '/parent',
        component: ParentComponent,
        children: [
            {
                path: 'child/:standalone',
                component: ChildComponent
            }
        ]
    }
  ]
  • 修改父组件
    我们在父组件中根据standalone取条件渲染。当standalone='standalone'时,就只渲染router-view,否则就使用“iframe”的方式。
<template v-if="$route.params.standalone!='standalone'">
    <h1>parent</h1>
    <router-view></router-view>
</template>
<template v-else>
    <router-view></router-view>
</template>

其效果如下
image

image
好处是实现了“iframe”和独立标签页两种形态,缺点是路径变长了

路由参数提升

但是在子路由上面加路由参数来实现这种控制,意味着父组件下的每一个子路由都要加路由参数。
这不免太繁琐,也不太合理。毕竟这种控制应当是父组件对子组件的控制。
更好的方式是将路由参数提升到父路由上。

const routes = [
    {
        path: '/',
        component: App,
    },
    {
        path: '/parent/:standalone',
        component: ParentComponent,
        children: [
            {
                path: 'child',
                component: ChildComponent
            }
        ]
    }
  ]

image

image

posted @ 2024-05-09 21:50  ggtc  阅读(25)  评论(0编辑  收藏  举报
//右下角目录