查看: 121|回复: 1

Vue跨页面通信实战:路由参数、Pinia/Vuex与localStorage详解

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在Vue项目开发中,不同路由页面之间的数据传递和状态同步是高频需求,比如从列表页跳转详情页传递ID,或者页面A操作后让页面B实时更新。本文基于实际开发场景,梳理三种最实用的跨页面通信方式:路由参数传递(query/params)、全局状态管理(Pinia/Vuex)、本地存储(localStorage/sessionStorage),覆盖Vue2和Vue3,每个方案均附带完整可运行的Demo代码与关键注意事项。

一、路由参数传递(页面跳转传值首选)

适用场景:列表页→详情页传递简单ID、名称等轻量数据,或传递敏感临时数据。分为 query 和 params 两种方式,按需选择。

1. query参数(路径可见,刷新不丢失)
优点:参数直接显示在URL中(如 /pageB?id=123),刷新页面仍保留,适合非敏感数据。

Vue3完整示例(组合式API):
  1. // 路由配置(router/index.js)
  2. import { createRouter, createWebHistory } from 'vue-router';
  3. import PageA from '@/views/PageA.vue';
  4. import PageB from '@/views/PageB.vue';
  5. const routes = [
  6.   { path: '/pageA', name: 'PageA', component: PageA },
  7.   { path: '/pageB', name: 'PageB', component: PageB }
  8. ];
  9. const router = createRouter({
  10.   history: createWebHistory(),
  11.   routes
  12. });
  13. export default router;
复制代码
  1. // 页面A(跳转方,@/views/PageA.vue)
  2. <template>
  3.   <div>
  4.     <h3>页面A</h3>
  5.     <router-link :to="{ path: '/pageB', query: { id: 123, name: 'Vue跨页面通信Demo' } }" class="btn">
  6.       点击跳转页面B(router-link)
  7.     </router-link>
  8.     <button @click="goToPageB" class="btn">点击跳转页面B(编程式)</button>
  9.   </div>
  10. </template>
  11. <script setup>
  12. import { useRouter } from 'vue-router';
  13. const router = useRouter();
  14. const goToPageB = () => {
  15.   router.push({
  16.     path: '/pageB',
  17.     query: { id: 123, name: 'Vue跨页面通信Demo' }
  18.   });
  19. };
  20. </script>
  21. <style scoped>
  22. .btn { margin: 0 10px; padding: 6px 12px; cursor: pointer; }
复制代码
  1. // 页面B(接收方,@/views/PageB.vue)
  2. <template>
  3.   <div>
  4.     <h3>页面B</h3>
  5.     <div>接收的ID:{{ id }}</div>
  6.     <div>接收的名称:{{ name }}</div>
  7.   </div>
  8. </template>
  9. <script setup>
  10. import { useRoute } from 'vue-router';
  11. import { ref, watch } from 'vue';
  12. const route = useRoute();
  13. const id = ref(Number(route.query.id));
  14. const name = ref(route.query.name);
  15. watch(() => route.query, (newQuery) => {
  16.   id.value = Number(newQuery.id);
  17.   name.value = newQuery.name;
  18. }, { immediate: true });
  19. </script>
复制代码

Vue2版本(选项式API)只需将 $router.push 和 $route.query 换成 this.$router 和 this.$route,并在 watch 中监听 '$route.query',结构类似,不再赘述。

2. params参数(路径不可见,适合敏感临时数据)
优点:参数不会出现在URL中,适合传递密码、token等敏感信息。注意:必须配合路由配置中的占位符(如 /pageB/:id/:name)使用,且跳转时必须使用 name,不能使用 path。刷新页面时若配置了占位符则不会丢失。

Vue3示例(仅展示差异部分):
  1. // 路由配置(需添加占位符)
  2. { path: '/pageB/:id/:name', name: 'PageB', component: PageB }
  3. // 页面A跳转(必须用name)
  4. router.push({ name: 'PageB', params: { id: 456, name: '敏感数据Demo' } });
  5. // 页面B接收
  6. const id = ref(Number(route.params.id));
  7. const name = ref(route.params.name);
复制代码

Vue2跳转方式:this.$router.push({ name: 'PageB', params: { id: 456, name: '敏感数据Demo' } }),接收使用 this.$route.params。

注意事项:
- query参数路径可见,适合简单字符串/数字;params参数路径不可见,但若未配置占位符,刷新后丢失。
- 传递对象/数组时,需先 JSON.stringify,接收时 JSON.parse,避免数据错乱。

二、全局状态管理(Pinia / Vuex)

适用场景:多个页面共享同一份数据(如用户信息、全局配置),且需要实时联动更新。Vue3 推荐 Pinia,Vue2 常用 Vuex。

1. Pinia(Vue3首选,更轻量简洁)
使用步骤:安装依赖(npm install pinia)→ 创建 Pinia 实例并注册 → 定义 store → 在组件中直接调用。
  1. // main.js 注册 Pinia
  2. import { createApp } from 'vue';
  3. import { createPinia } from 'pinia';
  4. import App from './App.vue';
  5. import router from './router';
  6. const app = createApp(App);
  7. app.use(createPinia());
  8. app.use(router);
  9. app.mount('#app');
复制代码
  1. // store/modules/user.js 定义仓库
  2. export const useUserStore = defineStore('user', {
  3.   state: () => ({
  4.     userInfo: { id: 1, name: '测试用户', age: 20 },
  5.     count: 0
  6.   }),
  7.   actions: {
  8.     setUserInfo(info) { this.userInfo = info; },
  9.     addCount() { this.count++; },
  10.     resetCount() { this.count = 0; }
  11.   }
  12. });
复制代码
  1. // 页面A(修改数据)
  2. <script setup>
  3. import { useUserStore } from '@/store/modules/user';
  4. const userStore = useUserStore();
  5. const updateUserInfo = () => {
  6.   userStore.setUserInfo({ id: 2, name: '新用户', age: 22 });
  7. };
  8. </script>
  9. <template>
  10.   <div>当前计数器:{{ userStore.count }}</div>
  11.   <button @click="userStore.addCount">+1</button>
  12. </template>
复制代码
  1. // 页面B(读取数据)
  2. <script setup>
  3. import { useUserStore } from '@/store/modules/user';
  4. const userStore = useUserStore();
  5. </script>
  6. <template>
  7.   <div>用户:{{ userStore.userInfo.name }}</div>
  8. </template>
复制代码

注意:Pinia 无需手动注册到 Vue,直接 useStore() 即可。数据在页面刷新后会丢失,需配合 localStorage 做持久化。

2. Vuex(Vue2 标准方案)
使用前安装 vuex@3,在 main.js 中 Vue.use(Vuex) 并注入 store。
  1. // store/index.js
  2. export default new Vuex.Store({
  3.   state: { userInfo: { id: 1, name: '测试用户', age: 20 }, count: 0 },
  4.   mutations: {
  5.     setUserInfo(state, info) { state.userInfo = info; },
  6.     addCount(state) { state.count++; },
  7.     resetCount(state) { state.count = 0; }
  8.   },
  9.   actions: {
  10.     addCountAsync({ commit }) { setTimeout(() => commit('addCount'), 1000); }
  11.   },
  12.   getters: { userName: state => state.userInfo.name }
  13. });
复制代码
  1. // 页面中通过 $store 访问
  2. this.$store.commit('addCount');
  3. this.$store.dispatch('addCountAsync');
  4. this.$store.state.count;
  5. this.$store.getters.userName;
复制代码

Vuex 的 mutation 必须同步,异步操作需要放在 action 中。使用 getters 简化读取。

三、localStorage / sessionStorage(本地存储持久化)

适用场景:需要跨页面持久保存的数据(如登录 token、用户偏好设置),刷新页面也不会丢失。localStorage 除非手动删除否则永久保存,sessionStorage 在关闭浏览器标签后清除。

推荐封装通用工具函数,方便统一管理对象序列化/反序列化:
  1. // utils/storage.js
  2. export const setLocal = (key, value) => {
  3.   const val = typeof value === 'object' ? JSON.stringify(value) : value;
  4.   localStorage.setItem(key, val);
  5. };
  6. export const getLocal = (key) => {
  7.   const val = localStorage.getItem(key);
  8.   try { return JSON.parse(val); } catch { return val; }
  9. };
  10. export const removeLocal = (key) => { localStorage.removeItem(key); };
  11. export const setSession = (key, value) => {
  12.   const val = typeof value === 'object' ? JSON.stringify(value) : value;
  13.   sessionStorage.setItem(key, val);
  14. };
  15. export const getSession = (key) => {
  16.   const val = sessionStorage.getItem(key);
  17.   try { return JSON.parse(val); } catch { return val; }
  18. };
  19. export const removeSession = (key) => { sessionStorage.removeItem(key); };
复制代码

在 Vue 组件中使用时,直接调用这些方法即可同步数据。若要实现“多页面实时同步”,可配合 storage 事件(window.addEventListener('storage', handler))或定时器轮询。

总结:以上三种方式覆盖了 Vue 跨页面通信的绝大多数场景:简单的跳转传值用路由参数;多页面全局共享用 Pinia/Vuex;需要持久化且不依赖框架层则用 localStorage。根据实际需求选择最合适的方案,避免过度设计。后续还会补充 EventBus、Cookie、postMessage 等进阶方式,但在日常开发中,掌握这三种已足以应对 80% 的需求。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Vue跨页面通信实战:路由参数、Pinia/Vuex与localStorage详解

感谢楼主分享,总结得很全面,代码示例也清晰易懂。我个人在项目里用得最多的是路由 query 传轻量数据,确实方便,但有时对象会先序列化一下。对于需要跨多个页面实时同步的状态,Pinia 确实比 Vuex 轻快不少,迁移成本也低。有个小疑问:params 配合占位符刷新不丢,但路径中还是会显示占位符里的值,严格来说不算完全隐藏吧?如果真要隐藏敏感数据,是不是还得结合 sessionStorage 或加密处理更稳妥?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-12 16:53 , Processed in 0.039312 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部