vue-router 4.1.4版本以上,打开新页面并隐式传参

情景

  1. 框架:Vue3 + Vite4 + VueRouter4.1.6
  2. 需求:现需要实现点击打开新页面,并把一些数据传过去
  3. 限制:
  • 数据量较大,有一定私密性,不适合用query传递;
  • 需要从session中获取token判断访问权限,因此需要用router.resolve携带session打开新页面
  • 使用params传参在4.1.4以上版本被抛弃了--> vue-router 4.1.4 CHANGELOG

尝试

官方推荐的params传参传参替代方案有:

  1. 用pinia等状态管理工具缓存数据 --> 无法跨页面使用
  2. 使用query或 /path/:param 这样的显示传参 --> 上面已经说了不适用于这次的需求
  3. 使用History API设置state --> 使用router-link无法携带session,在js中调用又只是当前页跳转
  4. 在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>
  1. 先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() 延时传递数据。

参考:window.open() 跳转其他系统,传参不放在URL 上

旧页面:

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();
posted @ 2023-06-02 10:13  宇宙野牛  阅读(1035)  评论(0编辑  收藏  举报