vue-router 如何实现支持外部链接

简介: vue项目中 不少场景会遇到外部链接的情况 vue-router官方 提供了扩展RouterLink 的方式 封装成一个组件AppLink.vue. 但是这种扩展方案 存在以下问题• 写法上 由 <router-link> 转变为 <AppLink>• 由于是封装的组件 就可能涉及到 style 样式的 作用域 不一样,可能会发生样式 失效• 项目需要额外 维护 AppLink.vue于是就想到采取另一种方案 扩展源码 来解决以上问题 , 实现 扩展版vue-router ,同时还可以增强一下 vue-router,使其 支持 restful 风格的链接

前言

vue项目中 不少场景会遇到外部链接的情况 vue-router官方 提供了扩展RouterLink 的方式 封装成一个组件AppLink.vue. 但是这种扩展方案 存在以下问题

  • 写法上 由 <router-link> 转变为 <AppLink>
  • 由于是封装的组件 就可能涉及到 style 样式作用域 不一样,可能会发生样式 失效
  • 项目需要额外 维护 AppLink.vue

于是就想到采取另一种方案 扩展源码 来解决以上问题 , 实现 扩展版vue-router ,同时还可以增强一下 vue-router,使其 支持 restful 风格的链接

以下为修改的核心源码

functionqueryToString(query) {
return ('?'+Object.keys(query)
            .map(key=> {
constvalue=query[key];
if (value==null)
return'';
if (Array.isArray(value)) {
returnvalue                    .map(val=>`${encodeURIComponent(key)}=${encodeURIComponent(val)}`)
                    .join('&');
            }
return`${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
        })
            .filter(Boolean)            .join('&'));
}
functionparamsToHref(to) {
const { path, params } =to;
constpathParams=Object.keys(params)
        .reduce((acc, key) => {
acc[key] =params[key];
returnacc;
    }, {});
constpathWithParams=path.replace(/:(\w+)/g, (_, key) => {
constvalue=pathParams[key];
if (value==null)
return':'+key;
if (Array.isArray(value)) {
returnvalue                .map(val=>encodeURIComponent(val))
                .join('/');
        }
returnencodeURIComponent(value);
    });
return`${pathWithParams}`;
}
functioncheckExternalLink(to) {
if (typeofto==='string'&&to.startsWith('http')) {
return { isExternalLink: true, href: to, isJavascript: false };
    }
elseif ((typeofto==='string'&&to.startsWith('javascript:')) || (typeofto.path==='string'&&to.path.startsWith('javascript:'))) {
return { isExternalLink: false, href: to, isJavascript: true };
    }
elseif (typeofto==='object'&&typeofto.path==='string'&&to.path.startsWith('http')) {
letpath=typeofto.params==='object'?paramsToHref(to) : to.path;
letqueryString=typeofto.query==='object'?queryToString(to.query) : '';
return { isExternalLink: true, href: path+queryString+ (to.hash?to.hash : ''), isJavascript: false };
    }
return { isExternalLink: false, href: '', isJavascript: false };
}
constRouterLinkImpl=/*#__PURE__*/defineComponent({
name: 'RouterLink',
props: {
to: {
type: [String, Object],
required: true,
        },
replace: Boolean,
activeClass: String,
// inactiveClass: String,exactActiveClass: String,
custom: Boolean,
ariaCurrentValue: {
type: String,
default: 'page',
        },
    },
useLink,
setup(props, { slots }) {
const { options } =inject(routerKey);
const { isExternalLink, href, isJavascript } =checkExternalLink(props.to);
constlink=!isExternalLink&&!isJavascript?reactive(useLink(props)) : { href: href, isActive: false, isExactActive: false, route: '', navigate: () =>Promise.resolve() };
constelClass=computed(() => ({
            [getLinkClass(props.activeClass, options.linkActiveClass, 'router-link-active')]: link.isActive,
// [getLinkClass(//   props.inactiveClass,//   options.linkInactiveClass,//   'router-link-inactive'// )]: !link.isExactActive,            [getLinkClass(props.exactActiveClass, options.linkExactActiveClass, 'router-link-exact-active')]: link.isExactActive,
        }));
return () => {
constchildren=slots.default&&slots.default(link);
returnprops.custom?children                : !isExternalLink?h('a', {
'aria-current': link.isExactActive?props.ariaCurrentValue                        : null,
href: link.href,
// this would override user added attrs but Vue will still add// the listener so we end up triggering bothonClick: link.navigate,
class: elClass.value,
                }, children) : h('a', {
href: link.href,
target: !isJavascript?"_blank" : null,
class: elClass.value,
                }, children);
        };
    },
});

扩展版vue-router

vue2.0 的项目 详解可见 @npm-pkg/vue-router vue3.0 的项目 详解可见 @npkg/vue-router@next

扩展版vue-router

扩展支持自动跳转到外部链接

快速上手

  • 通过CDN: <script src="https://unpkg.com/@npkg/vue-router@next"></script>
  • 将其添加到现有的Vue项目中:
npm install @npkg/vue-router@next
  |
  yarn add @npkg/vue-router@next

用法

将所有引用 vue-router 的地方用 @npkg/vue-router 去替代

创建路由实例

//# /src/router/index.js/* * 原代码 */import {
createRouter,
createWebHistory,
} from"vue-router";
// 创建路由实例exportconstrouter=createRouter({
history: createWebHistory(),
routes: [{
...  }]
  }
});
//----------------// 替换为以下代码//----------------/* * 新代码 */import {
createRouter,
createWebHistory,
} from"@npkg/vue-router";
//  创建路由实例exportconstrouter=createRouter({
history: createWebHistory(),
routes: [{
...  }]
  }
});
/* * 其他使用 */import { useRoute, useLink } from"@npkg/vue-router";
letrouter=useRouter()
router.push({path:'/'})

除了 Vue Router 原有用法,它还支持以下扩展写法

// 基础使用
<router-linkto="/"></router-link><router-linkto="/list"></router-link><router-linkto="https://github.com/npm-pkg/vue-router"></router-link><router-linkto="https://github.com/npm-pkg/vue-router?author=five-great"></router-link><router-linkto="https://github.com/npm-pkg/vue-router/tree/v4.0.15#readme"></router-link>//高级使用 restful 风格
<router-link:to="{path: '/'}"></router-link><router-link:to="{path: '/list'}"></router-link><router-link:to="{path:'https://github.com/npm-pkg/vue-router'}"></router-link><router-link:to="{path:'https://github.com/npm-pkg/vue-router', query:{author: 'five-great'}}"></router-link><router-link:to="{path:'https://github.com/npm-pkg/vue-router/tree/v4.0.15',hash:'#readme'}"></router-link><router-link:to="{path:'https://github.com/:org/:repo',params:{org:'npm-pkg',repo: 'vue-router'}}"></router-link><router-link:to="{path:'https://github.com/:org/:repo/tree/:v',query:{author: 'five-great'},params:{org:'npm-pkg',repo: 'vue-router',v:'v4.0.15'},hash:'#readme'}"></router-link>
目录
相关文章
|
存储 JavaScript 算法
Vue中如何实现动态路由
Vue中如何实现动态路由
91 1
|
14天前
|
JavaScript 前端开发
vue全局公共组件自动引入并注册,开发效率直接起飞!
【10月更文挑战第14天】vue全局公共组件自动引入并注册,开发效率直接起飞!
38 1
|
21天前
|
JavaScript 网络架构
Vue中实现分布式动态路由:基础步骤详解
Vue中实现分布式动态路由:基础步骤详解
19 2
|
20天前
|
前端开发 开发者 UED
你真的了解 Electron 的自动更新吗?揭秘AppUpdater 类的内部工作原理
本文由前端徐徐首发,深入探讨了 Electron 的自动更新工作原理,特别是 `electron-builder` 中 `AppUpdater` 类的源码分析,涵盖配置更新源、检查更新、下载更新、安装更新及事件通知等核心功能,帮助开发者更好地理解和使用 Electron 的自动更新机制。
45 0
你真的了解 Electron 的自动更新吗?揭秘AppUpdater 类的内部工作原理
|
13天前
|
JavaScript 前端开发 API
《vue3第六章》其他,包含:全局API的转移、其他改变
《vue3第六章》其他,包含:全局API的转移、其他改变
19 0
|
4月前
|
前端开发 JavaScript Java
前端 JS 经典:如何实现私有字段
前端 JS 经典:如何实现私有字段
22 1
|
6月前
|
JavaScript 前端开发 数据安全/隐私保护
Vue如何实现权限管理(动态路由addRoutes)
Vue如何实现权限管理(动态路由addRoutes)
337 1
|
6月前
|
前端开发 API SEO
vue-router原理以及两种模式区别
vue-router原理以及两种模式区别
38 1
|
6月前
|
JavaScript 网络架构
vue中动态路由是什么该如何实现
vue中动态路由是什么该如何实现
37 1
|
6月前
|
JavaScript
uniapp 跳转外部链接
uniapp 跳转外部链接
150 0