vue-router 4.1.4版本以上,打开新页面并隐式传参
情景
- 框架:Vue3 + Vite4 + VueRouter4.1.6
- 需求:现需要实现点击打开新页面,并把一些数据传过去
- 限制:
- 数据量较大,有一定私密性,不适合用query传递;
- 需要从session中获取token判断访问权限,因此需要用router.resolve携带session打开新页面
- 使用params传参在4.1.4以上版本被抛弃了--> vue-router 4.1.4 CHANGELOG
尝试
官方推荐的params传参传参替代方案有:
- 用pinia等状态管理工具缓存数据 --> 无法跨页面使用
- 使用query或 /path/:param 这样的显示传参 --> 上面已经说了不适用于这次的需求
- 使用History API设置state --> 使用router-link无法携带session,在js中调用又只是当前页跳转
- 在beforeEach里,用to.meta判断,再获取数据 --> 没有接口的情况下难以实现
除此之外,还尝试过
1.router-link。无法携带session,且params依旧无法传递
<router-link :to="{ name: 'thematicMap', params: { item } }" target="_blank"></router-link>
<router-link :to="{ name: 'thematicMap', state: { item } }" target="_blank"></router-link>
- 先query传参,再router.push去掉地址栏的参数。不介意地址栏会短暂出现参数可以尝试,下面代码也需要优化参数的获取方式
旧页面:
const routeUrl = router.resolve({
path: "/index/thematicMap",
query: { item: JSON.stringify(props.item) },
});
window.open(routeUrl.href, "_blank");
新页面:
const router = useRouter();
const route = useRoute();
router.push({ name: route.name, params: route.query });
目前发现的最佳方案
突然想起既然token可以放在session里带过去我要的数据当然也可以;_;
下面代码用pinia包了一层方便管理(当然也可以用持久化插件实现)
旧页面:
store.setItem(props.item);
新页面:
console.log("rsItem", remoteSenseStore.rsItem);
store:
const sessionRsItem = sessionStorage.getItem("rsItem") || "{}";
const rsItem = ref(JSON.parse(sessionRsItem));
const setItem = (item) => {
rsItem.value = item;
sessionStorage.setItem("rsItem", JSON.stringify(item));
};
另一可行方案
使用 window.postMessage()
延时传递数据。
旧页面:
const router = useRouter();
const origin = window.location.origin;
const toPreview = () => { // 点击触发,打开新页面
const routeUrl = router.resolve({
name: "thematicMap",
});
const childWindow = window.open(routeUrl.href, "_blank");
setTimeout(() => {
childWindow.postMessage(JSON.parse(JSON.stringify(props.item)), origin + routeUrl.href);
}, 500);
};
新页面:
const params = ref({});
const myOrigin = window.location.origin;
const initMessageListener = () => {
window.addEventListener("message", function (e) {
if (e.origin !== myOrigin) return; // 检测数据来源,这里是同源跳转的判断
const data = e.data;
params.value = data;
console.log("params", params.value);
});
};
initMessageListener();