核心思路

  1. 复用页面组件:让原页面和新页面共用同一个组件(避免重复开发)。
  2. 状态隔离:通过路由参数或状态标识,让组件根据 “是否为新页面” 维护独立的响应式状态(原页面和新页面的状态互不干扰)。
  3. 区分页面角色:用路由参数(如 isNewPage)标记当前页面是 “原页面” 还是 “新页面”,组件内部根据标记初始化和管理状态。
1. 复用组件设计(同一组件适配原页面和新页面)

创建一个可复用的页面组件(如 ReusablePage.vue),通过路由参数判断自身角色(原页面 / 新页面),并分别维护独立状态。

<!-- ReusablePage.vue(复用的页面组件) -->
<template>
  <div>
    <h2>{{ isNewPage ? '新页面' : '原页面' }}</h2>
    <p>当前状态:{{ currentState.count }} - {{ currentState.text }}</p>
    <button @click="increment">+1</button>
    <input v-model="currentState.text" placeholder="修改文本" />
    <button 
      v-if="!isNewPage" 
      @click="openNewPage"
    >
      基于当前状态生成新页面
    </button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';

// 路由工具
const route = useRoute();
const router = useRouter();

// 从路由参数判断是否为新页面
const isNewPage = ref(route.query.isNewPage === 'true');

// 状态容器(原页面和新页面的状态完全独立)
const currentState = ref({
  count: 0,
  text: '初始文本'
});

// 初始化状态:
// - 原页面:用默认初始值
// - 新页面:从路由参数接收原页面的状态并初始化
onMounted(() => {
  if (isNewPage.value) {
    // 新页面:解析原页面传递的状态(深拷贝避免引用关联)
    const originState = JSON.parse(decodeURIComponent(route.query.originState || '{}'));
    currentState.value = { ...originState }; // 浅拷贝(深层对象需用 JSON 深拷贝)
  }
});

// 原页面:打开新页面(复用当前组件,传递自身状态)
const openNewPage = () => {
  // 将当前状态转为 URL 安全的字符串(避免特殊字符)
  const originState = encodeURIComponent(JSON.stringify(currentState.value));
  // 跳转到同一个组件的路由,但标记为新页面并携带原状态
  router.push({
    path: '/reusable-page', // 复用同一路由路径(或新路径,只要组件相同即可)
    query: {
      isNewPage: 'true', // 标记为新页面
      originState: originState // 传递原页面状态
    }
  });
};

// 修改状态的方法(仅影响当前页面的 currentState)
const increment = () => {
  currentState.value.count++;
};
</script>
2. 路由配置(复用组件,通过参数区分页面)

在路由中配置一个路径,指向复用的组件,通过 query 参数(isNewPage)区分原页面和新页面。

// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import ReusablePage from '../views/ReusablePage.vue';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/reusable-page',
      name: 'ReusablePage',
      component: ReusablePage // 同一个组件适配两种页面角色
    }
  ]
});

export default router;
3. 新标签页场景(如需保留原页面)

如果需要在新标签页打开新页面(而非路由跳转),修改 openNewPage 方法,通过 window.open 传递状态:

// ReusablePage.vue 中修改 openNewPage 方法
const openNewPage = () => {
  const originState = encodeURIComponent(JSON.stringify(currentState.value));
  // 新标签页打开同一组件的路由,携带参数
  window.open(
    `/reusable-page?isNewPage=true&originState=${originState}`,
    '_blank'
  );
};

优势

  • 代码复用:无需开发新组件,直接复用已有页面逻辑。
  • 状态彻底隔离:利用 Vue 组件实例的独立性,确保原页面和新页面状态互不影响。
  • 扩展性强:可通过路由参数传递更多配置(如新页面的特殊权限、展示模式等)。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐