0%

【译】在JavaScript中使用URL

原文:https://blog.logrocket.com/working-urls-javascript/
使用ChatGPT协助翻译

URL 是任何 Web 应用的重要组成部分。如果您的应用需要向 API 发送请求,那么构造正确的 URL 就尤为重要。现代浏览器都支持的 URL API,为解析和操作 URL 提供了一种方便的方法。它可以轻松访问 URL 的各个部分。

了解 URL 的组成部分

使用 JavaScript 操作 URL

让我们看以下示例 URL:

1
https://example.com/api/search?query=foo&sort=asc#results

这个 URL 包括以下几个部分:

  • 协议 (Protocol): https
  • 主机 (Host): example.com
  • 路径名称 (Path name): /api/search
  • 查询字符串 (Query string): ?query=foo&sort=asc
  • 哈希 (Hash): #results

通过现代 JavaScript,我们可以轻松解析这些不同的部分。


解析 URL

在支持 URL API 之前,开发者经常使用 <a> 元素解析 URL。例如,提取查询字符串可以这样写:

1
2
3
4
5
function getQueryString(url) {
const link = document.createElement("a");
link.href = url;
return link.search;
}

缺点:

  1. 需要 DOM 环境,因此不能在 Node.js 环境中运行。
  2. 缺乏错误处理,例如传入无效的 URL 时不会抛出错误。

使用 URL API,我们可以更安全、更简单地解析 URL。只需将 URL 传递给 URL 构造函数。如果 URL 是有效的,构造函数会返回一个包含该 URL 各部分属性的对象:

1
2
3
4
const url = new URL("https://example.com/api/search?query=foobar");
console.log(url.host); // example.com
console.log(url.pathname); // /api/search
console.log(url.search); // ?query=foobar

解析查询字符串

查询字符串有两种访问方式:

  1. 使用 search 属性,返回完整的查询字符串(包括 ?)。
  2. 使用 searchParams 属性,返回一个 URLSearchParams 对象。

获取特定参数值

使用 searchParamsget 方法,可以根据参数名称获取值:

1
2
3
4
5
const url = new URL(
"https://example.com/api/search?query=foobar&maxResults=10"
);
console.log(url.searchParams.get("query")); // foobar
console.log(url.searchParams.get("maxResults")); // 10

获取同名参数的所有值

使用 getAll 方法返回同名参数的值数组:

1
2
3
4
const url = new URL(
"https://example.com/api/search?tag=tag1&tag=tag2&tag=tag3"
);
console.log(url.searchParams.getAll("tag")); // ['tag1', 'tag2', 'tag3']

构建查询字符串

手动构建查询字符串时,需要注意转义特殊字符,例如 & 要编码为 %26

1
2
3
4
let queryString = "foo=bar";
queryString += "&baz=qux";
queryString += "&tag=" + encodeURIComponent("one&two");
console.log(queryString); // foo=bar&baz=qux&tag=one%26two

使用 URLSearchParams 对象可以更安全地构建查询字符串:

1
2
3
4
5
const params = new URLSearchParams();
params.append("foo", "bar");
params.append("baz", "qux");
params.append("tag", "one&two");
console.log(params.toString()); // foo=bar&baz=qux&tag=one%26two

优点:

  1. 自动处理 & 分隔符。
  2. 自动对参数值进行 URI 编码。
  3. 无需使用字符串拼接。

遍历查询参数

如果不用 URLSearchParams 对象,需要多次分割字符串来遍历查询参数。例如:

1
2
3
4
5
6
function listQueryParams(queryString) {
queryString.split("&").forEach((param) => {
const [key, value] = param.split("=");
console.log(`${key}: ${decodeURIComponent(value)}`);
});
}

使用 URLSearchParamsentries 方法可以更简洁地遍历键值对:

1
2
3
4
5
6
function listQueryParams(queryString) {
const params = new URLSearchParams(queryString);
for (const [key, value] of params.entries()) {
console.log(`${key}: ${value}`);
}
}

构建完整的 URL

以下是通过基础 URL 和查询参数构建完整 URL 的示例:

1
2
3
4
5
6
7
const url = new URL("https://example.com/api/search");
url.searchParams.append("query", "test");
url.searchParams.append("tag", "tag1");
url.searchParams.append("tag", "tag2");

console.log(url.toString());
// 输出: https://example.com/api/search?query=test&tag=tag1&tag=tag2

验证 URL 是否有效

尽量避免使用正则表达式来验证 URL,可以使用 URL API 的构造函数:

1
2
3
4
5
6
7
8
function isValidURL(url) {
try {
new URL(url);
return true;
} catch (error) {
return false;
}
}

或者使用 URL.canParse 方法(部分浏览器支持):

1
2
console.log(URL.canParse("https://example.com")); // true
console.log(URL.canParse("invalid-url")); // false

构建相对 URL

URL 构造函数允许通过一个基础 URL 来构建相对 URL:

1
2
3
4
5
console.log(new URL("/about", "https://example.com").href);
// 输出: https://example.com/about

console.log(new URL("../profile", "https://example.com/users/123").href);
// 输出: https://example.com/profile

如果基础 URL 无效或不完整,会抛出错误:

1
new URL("../profile", "/about"); // 报错

使用 window.location 对象

window.location 表示当前页面的 URL,但它不是一个 URL 对象,可以通过将其传递给 URL 构造函数来创建一个完整的 URL 对象:

1
new URL("/profile", window.location).href;

使用 URLPattern 匹配 URL 模式

以下是匹配用户 ID 的示例:

1
2
3
const pattern = new URLPattern("https://example.com/api/users/:userId/profile");
const matcher = pattern.exec("https://example.com/api/users/123/profile");
console.log(matcher.pathname.groups.userId); // 123

总结

URL API 提供了一种安全、便捷的方式来操作 URL,而不需要手动解析或使用正则表达式。对于复杂模式匹配,URLPattern 提供了强大的能力,但它目前的浏览器支持尚不全面。

扫码加入技术交流群🖱️
QR code