vue.js 2路由 两个子挂载

admin 106 0
Vue.js 2中,Vue Router作为官方路由管理器,通过嵌套路由(子挂载)实现多级页面结构,开发者可在父路由配置中通过children属性定义子路由,形成层级关系,如“/user”下嵌套“/user/profile”与“/user/settings”,使用组件作为子路由渲染出口,配合router-link导航,实现页面模块化拆分,这种模式适用于复杂场景(如后台管理多级菜单),既保持路由清晰层级,又提升代码可维护性,是构建单页面应用(SPA)的核心实践。

Vue.js 2 中实现双路由子挂载:模块化路由管理实践

在复杂的前端应用开发中,随着业务模块的拆分和功能复杂度的提升,单一的全局路由系统往往难以满足模块化、独立管理的需求,Vue.js 2 通过 Vue Router 提供了灵活的路由机制,支持在同一个页面中通过多个挂载点实现"双子挂载"——即两个独立的路由系统分别挂载到不同的 DOM 节点,各自管理模块内的路由逻辑,这种架构模式特别适用于大型企业级应用、多租户系统或需要严格模块隔离的场景,本文将详细介绍 Vue.js 2 中双路由子挂载的实现原理、具体步骤及最佳实践。

核心概念:什么是"双路由子挂载"?

在 Vue.js 2 的路由体系中,子挂载并非指嵌套路由(嵌套路由是在一个路由组件内通过 <router-view> 展示子路由,仍属于同一路由系统),而是指两个独立的 Vue Router 实例分别挂载到不同的 DOM 节点,形成两个互不干扰的路由作用域,每个路由实例拥有自己的路由配置、导航守卫和组件渲染逻辑,适用于需要将不同模块完全隔离的场景。

双路由子挂载与嵌套路由的区别

特性 双路由子挂载 嵌套路由
路由实例数量 多个独立实例 单一实例
URL 管理 各自独立 父子级联
导航守卫 独立配置 可继承父级
适用场景 模块完全隔离 层级结构清晰

典型应用场景

  1. 主业务模块与后台管理模块分离:前台展示路由与后台管理路由完全隔离
  2. 多租户系统:不同租户拥有独立路由空间
  3. 插件化架构:第三方插件拥有自己的路由系统
  4. 微前端集成:不同子应用拥有独立路由管理

实现双路由子挂载的步骤

准备环境:引入 Vue.js 2 和 Vue Router

确保项目中已安装 Vue.js 2 和 Vue Router(通过 CDN 或 npm 安装):

<!-- 通过 CDN 引入 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.js"></script>

定义两个独立的路由配置

为两个子模块分别创建路由配置对象,每个对象包含独立的路由规则,我们有两个模块:"用户模块"和"商品模块",各自有不同的路由页面。

// 用户模块路由配置
const userRoutes = [
  { 
    path: '/user/profile', 
    component: { 
      template: `
        <div>
          <h2>用户个人中心</h2>
          <p>这是用户模块的个人信息页</p>
          <button @click="goToSettings">前往设置</button>
        </div>
      `,
      methods: {
        goToSettings() {
          this.$router.push('/user/settings');
        }
      }
    } 
  },
  { 
    path: '/user/settings', 
    component: { 
      template: `
        <div>
          <h2>用户设置</h2>
          <p>这是用户模块的设置页</p>
          <button @click="goBack">返回</button>
        </div>
      `,
      methods: {
        goBack() {
          this.$router.go(-1);
        }
      }
    } 
  }
];
// 商品模块路由配置
const productRoutes = [
  { 
    path: '/product/list', 
    component: { 
      template: `
        <div>
          <h2>商品列表</h2>
          <p>这是商品模块的商品列表页</p>
          <ul>
            <li v-for="product in products" :key="product.id">
              <router-link :to="`/product/detail/${product.id}`">
                {{ product.name }}
              </router-link>
            </li>
          </ul>
        </div>
      `,
      data() {
        return {
          products: [
            { id: 1, name: '商品A' },
            { id: 2, name: '商品B' },
            { id: 3, name: '商品C' }
          ]
        };
      }
    } 
  },
  { 
    path: '/product/detail/:id', 
    component: { 
      template: `
        <div>
          <h2>商品详情</h2>
          <p>商品ID: {{ productId }}</p>
          <button @click="goBack">返回列表</button>
        </div>
      `,
      computed: {
        productId() {
          return this.$route.params.id;
        }
      },
      methods: {
        goBack() {
          this.$router.push('/product/list');
        }
      }
    } 
  }
];

创建两个独立的 Vue Router 实例

基于上述路由配置,分别创建两个 Vue Router 实例,每个实例管理一个模块的路由逻辑:

// 用户模块路由实例
const userRouter = new VueRouter({
  routes: userRoutes,
  // 可单独配置模式(history/hash/abstract)
  mode: 'history',
  // 可配置基础路径,避免路由冲突
  base: '/user'
});
// 商品模块路由实例
const productRouter = new VueRouter({
  routes: productRoutes,
  mode: 'history',
  base: '/product'
});

在 Vue 实例中挂载路由实例

创建 Vue 根实例,并将两个路由实例分别挂载到不同的 DOM 节点:

// 创建 Vue 根实例
const app = new Vue({
  el: '#app',
  template: `
    <div>
      <h1>双路由子挂载示例</h1>
      <!-- 用户模块路由挂载点 -->
      <div class="user-module">
        <h3>用户模块</h3>
        <router-view></router-view>
      </div>
      <!-- 商品模块路由挂载点 -->
      <div class="product-module">
        <h3>商品模块</h3>
        <router-view></router-view>
      </div>
    </div>
  `,
  // 为每个 router-view 指定对应的 router 实例
  router: userRouter, // 默认路由实例
  // 使用 provide/inject 将两个路由实例注入子组件
  provide() {
    return {
      userRouter: userRouter,
      productRouter: productRouter
    };
  }
});

为不同的 router-view 指定路由实例

为了使不同的 <router-view> 使用不同的路由实例,我们需要自定义一个 router-view 组件:

// 自定义 router-view 组件
const AsyncRouterView = {
  functional: true,
  props: {
    name: {
      type: String,
      default: 'default'
    },
    router: {
      type: Object,
      required: true
    }
  },
  render(createElement, context) {
    const { name, router } = context.props;
    const component = router.getMatchedComponents()[0];
    return createElement(component);
  }
};
// 在 Vue 实例中使用
const app = new Vue({
  el: '#app',
  components: {
    AsyncRouterView
  },
  template: `
    <div>
      <h1>双路由子挂载示例</h1>
      <!-- 用户模块路由挂载点 -->
      <div class="user-module">
        <h3>用户模块</h3>
        <async-router-view :router="userRouter"></async-router-view>
      </div>
      <!-- 商品模块路由挂载点 -->
      <div class="product-module">
        <h3>商品模块</h3>
        <async-router-view :router="productRouter"></async-router-view>
      </div>
    </div>
  `,
  data() {
    return {
      userRouter,

标签: #js 2 #路由 #子挂载