这样的访问/sbKLEy/:id路径的时候,直接就会跳转到/consectetur/adipiscing/elit/:id。
query、params也都能正常重定向到源页面。
这个方案缺点就是只能缩短URL的 路径 部分。如果你的页面上有大量的查询参数部分,那这个方法能缩短的字符很有限。
好了,跳转功能没有问题,接下来就可以实现分享功能了。
分享功能
我们分享的逻辑是,用当前的路由地址去 短链接路由表 查询有无对应地址。有则使用短链接为分享路径,无则继续使用当前路由。然后将分享路径写入到粘贴板。
在实现分享功能之前,先准备两个工具函数:
/**
* 根据给定的路径和参数对象,生成一个包含占位符的路径字符串
* @param {Object} route - 包含路径和参数的对象
* @param {string} route.path - 路径字符串
* @param {Object} route.params - 参数对象
* @returns {string} - 替换参数后的路径字符串,其中参数被替换为占位符
* @example
* 输入: "/users/123", { id: "123" }
* 输出: "/users/:id"
*/
function getSourcePath(path, params) {
let sourcePath = path;
// 按占位符名称的长度排序,从长到短,避免替换错误
const keys = Object.keys(params).sort((a, b) => b.length - a.length);
for (const key of keys) {
if (!Object.hasOwnProperty.call(params, key)) continue;
const value = params[key];
const regex = new RegExp(value, 'g'); // 全局匹配该值
sourcePath = sourcePath.replace(regex, `:${key}`);
}
return sourcePath.replace(//+$/, "");
}
/**
* 根据给定的路径和参数对象,生成一个包含实际参数值的路径字符串
* @param {string} path - 路径模板,其中包含占位符,如 ":id"
* @param {Object} params - 参数对象,包含占位符对应的值
* @returns {string} - 替换占位符后的实际路径字符串
* @example
* 输入: "/users/:id", { id: "123" }
* 输出: "/users/123"
*/
function getParamsPath(path, params) {
let paramsPath = path;
// 遍历占位符,确保每个占位符都能被替换
for (const key in params) {
if (!Object.hasOwnProperty.call(params, key)) continue;
const value = params[key];
const regex = new RegExp(`:${key}(?=\/|$)`, 'g'); // 确保只替换占位符
paramsPath = paramsPath.replace(regex, value);
}
return paramsPath.replace(//+$/, "");
}
这两个函数是相反的功能,一个是将/users/123转为/users/:id,另一个是将/users/:id转回/users/123。
getSourcePath方法是按值查找替换,在两个param值相同的情况下可能会替换错误。这里有需要的可以深入再完善一下。
因为我项目内没有多个param的路由,所以就不再继续完善该函数了。
接下来就是分享函数 handleShare
export function handleShare (route) {
// 待分享的路由路径
let sharePath = route.path
// 源路径
const sourcePath = getSourcePath(route.path, route.params)
// 映射的短链接路由
const redirectMapRoute = redirectMap.find(item => item.redirect === sourcePath)
if (redirectMapRoute) {
sharePath = getParamsPath(redirectMapRoute.path, route.params)
}
// 将完整路径中的路径替换为分享路径-省去处理 query 部分
sharePath = route.fullPath.replace(route.path, sharePath)
// 复制内容
const shareUrl = `【${document.title}】 ${window.location.origin + sharePath}`
// 将分享路径复制到剪切板,并且处理兼容问题
try {
navigator.clipboard.writeText(shareUrl)
.then(() => {
Message({
message: '分享链接复制成功',
type: 'success'
})
})
} catch (err) {
var copyInput = document.createElement('input')
copyInput.setAttribute('value', shareUrl)
document.body.appendChild(copyInput)
copyInput.select()
document.execCommand('copy')
document.body.removeChild(copyInput)
Message({
message: '分享链接复制成功',
type: 'success'
})
}
}
功能大致就是:从短链接路由表中查找是否有对应映射的路由,有就使用该短链接路由作为分享地址,然后复制。
随后只需要在页面分享按钮的上添加上这个方法调用就ok了。
// vue2
<div @click="handleShare($route)">
分享
</div>
// vue3
<div @click="handleShare(route)">
分享
</div>
...
import { useRoute } from 'vue-router'
const route = useRoute()