一、概念概述
这段代码来自 Vue 生态中常见的工具模块,主要用于判断与解析 URL 类型,包括:
- 判断 URL 是否是相对路径(
isRelativeUrl); - 判断 URL 是否为外部链接(
isExternalUrl); - 判断 URL 是否为
data:协议(isDataUrl); - 对 URL 进行安全解析(
parseUrl、parseUriParts)。
这些函数在 Vue 的构建阶段(尤其是组件编译与资源路径重写时)起到关键作用。
二、原理解析
1. 相对路径判断:isRelativeUrl()
typescript
export function isRelativeUrl(url: string): boolean {
const firstChar = url.charAt(0)
return firstChar === '.' || firstChar === '~' || firstChar === '@'
}
行级注释:
-
url.charAt(0):取字符串第一个字符。 -
判断条件:
"."→ 常规相对路径,如./assets/img.png;"~"→ webpack 早期用于模块路径的前缀;"@"→ Vue CLI 默认的src路径别名。
核心逻辑:
通过首字符判断路径是否指向项目内的相对资源或别名路径,而非 HTTP(S) 资源。
2. 外部链接判断:isExternalUrl()
typescript
const externalRE = /^(?:https?:)?///
export function isExternalUrl(url: string): boolean {
return externalRE.test(url)
}
行级注释:
-
正则
/^(?:https?:)?///:- 匹配
http://或https://; ?:表示非捕获组;- 可选的协议部分允许支持
//example.com这种"协议相对 URL"。
- 匹配
原理说明:
通过正则匹配 URL 前缀来识别是否为外部资源链接,常用于判断是否需要打包或重写路径。
3. Data URL 判断:isDataUrl()
typescript
const dataUrlRE = /^\s*data:/i
export function isDataUrl(url: string): boolean {
return dataUrlRE.test(url)
}
行级注释:
^\s*data:匹配以可选空白符后跟data:的字符串;i标志表示忽略大小写。
应用场景:
用于判断内嵌资源,如:
css
<img src="data:image/png;base64,..." />
此类资源在构建阶段通常无需处理或重写。
4. URL 解析函数:parseUrl()
ini
export function parseUrl(url: string): UrlWithStringQuery {
const firstChar = url.charAt(0)
if (firstChar === '~') {
const secondChar = url.charAt(1)
url = url.slice(secondChar === '/' ? 2 : 1)
}
return parseUriParts(url)
}
行级注释:
-
针对以
~开头的路径(如~assets/img.png):- 若第二字符为
/,则去掉前两个字符; - 否则仅去掉第一个字符;
- 若第二字符为
-
最后调用
parseUriParts()进行真正的解析。
背景说明:
~ 是 webpack 中表示从 node_modules 开始解析的标志。Vue 的构建工具需要去掉它以获得合法路径。
5. 底层解析函数:parseUriParts()
php
function parseUriParts(urlString: string): UrlWithStringQuery {
return uriParse(isString(urlString) ? urlString : '', false, true)
}
行级注释:
- 使用 Node.js 内置的
url.parse()(即uriParse的别名); - 第一个参数:要解析的字符串;
- 第二个参数
false:表示不自动解析查询参数; - 第三个参数
true:允许没有协议的路径,如//cdn.com/img.png。
安全性:
- 若输入不是字符串(
isString(urlString)),则传入空字符串防止抛出TypeError。
三、对比分析
| 功能 | 匹配方式 | 特征 | 示例输入 | 输出结果 |
|---|---|---|---|---|
isRelativeUrl |
字符首位匹配 | 相对或别名路径 | ./logo.png |
✅ |
isExternalUrl |
正则匹配 | HTTP(S) 或协议相对路径 | https://vuejs.org |
✅ |
isDataUrl |
正则匹配 | 内嵌资源 | data:image/png;base64,... |
✅ |
parseUrl |
路径清洗 + Node 解析 | 统一解析 URL | ~@/assets/a.png |
{ protocol, pathname, ... } |
四、实践示例
arduino
console.log(isRelativeUrl('./src/main.js')) // true
console.log(isExternalUrl('https://vuejs.org')) // true
console.log(isDataUrl('data:text/plain;base64,SGVsbG8=')) // true
console.log(parseUrl('~@/assets/logo.png'))
输出说明:
- 前三项返回布尔值;
- 最后一项返回 Node.js 的
UrlWithStringQuery对象,如:
json
{
"protocol": null,
"slashes": null,
"auth": null,
"host": null,
"port": null,
"hostname": null,
"hash": null,
"search": null,
"query": null,
"pathname": "@/assets/logo.png",
"path": "@/assets/logo.png",
"href": "@/assets/logo.png"
}
五、拓展应用
-
Vite / Vue SFC 编译阶段:
- 判断资源是否应由构建工具处理或原样保留。
- 用于
<img src="...">、<link href="...">等路径转换。
-
Webpack Loader 转换规则:
- 当
require('~assets/logo.png')出现时,解析为真实文件路径。
- 当
-
插件开发:
- 在自定义编译插件中,复用这些函数可准确判断 URL 类型,避免误处理。
六、潜在问题与注意点
-
Node.js URL API 兼容性:
url.parse()在 Node 18+ 中被标记为过时,推荐改用new URL()。
-
特殊协议支持:
- 当前正则未涵盖
ftp://、file://等协议,如需兼容需扩展正则。
- 当前正则未涵盖
-
安全输入检查:
- 尽管使用
isString做了基础防护,但若输入为空或恶意字符仍可能引发逻辑错误。
- 尽管使用
-
构建环境依赖:
- 此模块依赖 Node.js 的
url模块,浏览器端执行需额外 polyfill。
- 此模块依赖 Node.js 的
七、总结
这段工具函数看似简单,但在 Vue 的构建体系中扮演了基础"路径识别层"的角色。
它确保在模板解析、资源导入、依赖重写等阶段,路径被正确识别、转换与安全解析。
本文部分内容借助 AI 辅助生成,并由作者整理审核。