URL Pattern API
注意:此功能在 Web Workers 中可用。
URL 模式 API 定義了一種用於建立 URL 模式匹配器的語法。這些模式可以與 URL 或單個 URL 元件進行匹配。
概念與用法
模式使用 URLPattern 介面指定。模式語法基於 path-to-regexp 庫的語法。模式可以包含:
- 將被精確匹配的字面字串。
- 匹配任何字元的萬用字元 (
/posts/*)。 - 提取匹配 URL 部分的命名組 (
/books/:id)。 - 使模式部分可選或多次匹配的非捕獲組 (
/books{/old}?)。 RegExp組 (/books/(\\d+)) 可進行任意複雜的正則表示式匹配。請注意,括號不是正則表示式的一部分,而是將其內容定義為正則表示式。某些 API 禁止在URLPattern物件中使用正則表示式組。hasRegExpGroups屬性指示是否使用了正則表示式組。
您可以在下面的模式語法部分找到有關語法的詳細資訊。
介面
URLPattern-
表示可以匹配 URL 或 URL 部分的模式。該模式可以包含捕獲組,用於提取匹配 URL 的部分。
模式語法
模式的語法基於 path-to-regexp JavaScript 庫。此語法類似於 Ruby on Rails 或 Express 或 Next.js 等 JavaScript 框架中使用的語法。
固定文字和捕獲組
每個模式都可以包含固定文字和組的組合。固定文字是精確匹配的字元序列。組根據匹配規則匹配任意字串。每個 URL 部分都有其自己的預設規則,如下所述,但它們可以被覆蓋。
// A pattern matching some fixed text
const pattern = new URLPattern({ pathname: "/books" });
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.exec("https://example.com/books").pathname.groups); // {}
// A pattern matching with a named group
const pattern = new URLPattern({ pathname: "/books/:id" });
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.exec("https://example.com/books/123").pathname.groups); // { id: '123' }
段萬用字元
預設情況下,匹配 URL 的 pathname 部分的組將匹配除正斜槓 (/) 之外的所有字元。在 hostname 部分中,該組將匹配除點 (.) 之外的所有字元。在所有其他部分中,該組將匹配所有字元。段萬用字元是非貪婪的,這意味著它將匹配最短的可能字串。
正則表示式匹配器
您可以為每個組指定一個正則表示式,而不是使用組的預設匹配規則,方法是在括號中指定它。此正則表示式定義了組的匹配規則。下面是一個命名組上的正則表示式匹配器的示例,它將組限制為僅當它包含一個或多個數字時才匹配。
const pattern1 = new URLPattern("/books/:id(\\d+)", "https://example.com");
console.log(pattern1.test("https://example.com/books/123")); // true
console.log(pattern1.test("https://example.com/books/abc")); // false
console.log(pattern1.test("https://example.com/books/")); // false
您還可以使用物件語法構造 URLPattern 時使用正則表示式。
const pattern2 = new URLPattern({ pathname: "/books/:id(\\d+)" });
console.log(pattern2.test("https://example.com/books/123")); // true
console.log(pattern2.test("https://example.com/books/abc")); // false
console.log(pattern2.test("https://example.com/books/")); // false
路徑名匹配
pathname URL 部分始終以 / 開頭。如果您在正則表示式中省略 /,則匹配將失敗。下面的示例:
// Doesn't match, because omits the `/`
const pattern1 = new URLPattern({ pathname: "(b.*)" });
console.log(pattern1.test("https://example.com/b")); // false
console.log(pattern1.test("https://example.com/ba")); // false
以下示例包含 /
// Matches URL where path is exactly "/b"
const pattern2 = new URLPattern({ pathname: "(/b)" });
console.log(pattern2.test("https://example.com/b")); // true
console.log(pattern2.test("https://example.com/ba")); // false
// Matches URL where path is /b followed by any number of characters
const pattern3 = new URLPattern({ pathname: "(/b.*)" });
console.log(pattern3.test("https://example.com/b")); // true
console.log(pattern3.test("https://example.com/ba")); // true
行首和行尾錨點
行首錨點 (^) 和行尾錨點 ($) 用於將模式分別錨定到測試字串的開頭和結尾。雖然這些可以為 URL 部分的開頭和結尾指定,但它們是冗餘的。這是因為所有 URL 部分都隱式地以 ^ 錨點為字首,並以 $ 錨點為字尾。
以下程式碼演示了是否指定 ^ 都沒有關係。該示例在 protocol URL 部分中使用模式,但 URL 的其他部分行為相同。
// with `^` in protocol
const pattern1 = new URLPattern({ protocol: "(^https?)" });
console.log(pattern1.test("https://example.com/index.html")); // true
// without `^` in protocol
const pattern2 = new URLPattern({ protocol: "(https?)" });
console.log(pattern2.test("https://example.com/index.html")); // true
以下程式碼演示了是否指定 $ 都沒有關係。
// with `$` in pathname
const pattern1 = new URLPattern({ pathname: "(/path$)" });
console.log(pattern1.test("https://example.com/path")); // true
// without `$` in pathname
const pattern2 = new URLPattern({ pathname: "(/path)" });
console.log(pattern2.test("https://example.com/path")); // true
// with `$` in hash
const pattern3 = new URLPattern({ hash: "(/hash$)" });
console.log(pattern3.test("https://example.com/#hash")); // true
// without `$` in hash
const pattern4 = new URLPattern({ hash: "(/hash)" });
console.log(pattern4.test("https://example.com/#hash")); // true
先行和後行斷言
先行斷言和後行斷言允許您指定當前解析位置之前或之後的文字匹配特定模式,而無需捕獲該匹配或消耗這些字元。
有四種類型的斷言:
(?=...):正向先行斷言指定後續字元必須匹配的模式。(?!...):負向先行斷言指定後續字元不得匹配的模式。(?<=...):正向後行斷言指定先行字元必須匹配的模式。(?<!...):負向後行斷言指定先行字元不得匹配的模式。
在使用先行和後行斷言與 URLPattern 時要小心,因為您可能會發現某些行為不直觀。例如,您希望以下先行斷言匹配 /ab 的 pathname,但事實並非如此。
const pattern = new URLPattern({ pathname: "(/a(?=b))" });
console.log(pattern.test("https://example.com/ab")); // false
URLPattern 引擎將測試字串與 pathname 模式匹配,首先找到 /a 的匹配項,然後斷言測試 URL 中的下一個字元是 b——但不會消耗它。引擎在未消耗的字元 b 處繼續匹配測試 URL,但模式中沒有剩餘的內容可以與之匹配,這會導致匹配失敗。
為了使匹配成功,模式必須消耗測試字串中的所有字元。要消耗 b 字元,您可以在表示式的末尾新增 b,新增 . 以匹配任何字元,或新增 .* 以匹配先行斷言之後的所有字元。
// positive-lookahead
const pattern1 = new URLPattern({ pathname: "(/a(?=b).*)" });
console.log(pattern1.test("https://example.com/ab")); // true
console.log(pattern1.test("https://example.com/ax")); // false
下一個示例顯示了 /a 的負向先行匹配,它後面不跟 b。請注意,斷言後面跟著 .* 以消耗斷言匹配的字元。
// negative-lookahead - matches /a<not b><anything>
const pattern2 = new URLPattern({ pathname: "(/a(?!b).*)" });
console.log(pattern2.test("https://example.com/ab")); // false
console.log(pattern2.test("https://example.com/ax")); // true
以下示例顯示了匹配 /ba 等路徑名的正向後行匹配。該模式匹配 /,然後是 . 以消耗下一個字元,然後斷言前一個字元是 b,然後是 a。
// positive-lookbehind
const pattern = new URLPattern({ pathname: "(/.(?<=b)a)" });
console.log(pattern.test("https://example.com/ba")); // true
console.log(pattern.test("https://example.com/xa")); // false
此示例顯示了一個負向後行匹配,它匹配 /<not b>a 等路徑名。該模式匹配 /,然後是 . 以消耗下一個字元 (x),然後斷言前一個字元不是 b,然後是 a。
// negative-lookbehind
const pattern4 = new URLPattern({ pathname: "(/.*(?<!b)a)" });
console.log(pattern4.test("https://example.com/ba")); // false
console.log(pattern4.test("https://example.com/xa")); // true
其他正則表示式匹配器限制
某些其他正則表示式模式可能無法按您預期的方式工作:
-
在 URLPattern 中的範圍表示式中,括號需要轉義,儘管它們在 RegExp 中不需要。
jsnew URLPattern({ pathname: "([()])" }); // throws new URLPattern({ pathname: "([\\(\\)])" }); // ok new RegExp("[()]"); // ok new RegExp("[\\(\\)]"); // ok
無名組和命名組
組可以是命名組或無名組。命名組透過在組名前新增冒號 (:) 來指定。未以冒號和名稱為字首的正則表示式組是無名組。無名組根據它們在模式中的順序在匹配結果中按數字索引。
// A named group
const pattern = new URLPattern("/books/:id(\\d+)", "https://example.com");
console.log(pattern.exec("https://example.com/books/123").pathname.groups); // { id: '123' }
// An unnamed group
const pattern = new URLPattern("/books/(\\d+)", "https://example.com");
console.log(pattern.exec("https://example.com/books/123").pathname.groups); // { '0': '123' }
組修飾符
組也可以有修飾符。這些在組名之後(如果存在正則表示式,則在正則表示式之後)指定。有三個修飾符:? 使組可選,+ 使組重複一次或多次,以及 * 使組重複零次或多次。
// An optional group
const pattern = new URLPattern("/books/:id?", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.test("https://example.com/books/")); // false
console.log(pattern.test("https://example.com/books/123/456")); // false
console.log(pattern.test("https://example.com/books/123/456/789")); // false
// A repeating group with a minimum of one
const pattern = new URLPattern("/books/:id+", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // false
console.log(pattern.test("https://example.com/books/")); // false
console.log(pattern.test("https://example.com/books/123/456")); // true
console.log(pattern.test("https://example.com/books/123/456/789")); // true
// A repeating group with a minimum of zero
const pattern = new URLPattern("/books/:id*", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.test("https://example.com/books/")); // false
console.log(pattern.test("https://example.com/books/123/456")); // true
console.log(pattern.test("https://example.com/books/123/456/789")); // true
組分隔符
模式還可以包含組分隔符。這些是括在大括號 ({}) 中的模式片段。這些組分隔符不像捕獲組那樣在匹配結果中被捕獲,但仍然可以對它們應用修飾符,就像組一樣。如果組分隔符未被修飾符修改,則它們被視為其中的項只是父模式的一部分。組分隔符不能包含其他組分隔符,但可以包含任何其他模式項(捕獲組、正則表示式、萬用字元或固定文字)。
// A group delimiter with a ? (optional) modifier
const pattern = new URLPattern("/book{s}?", "https://example.com");
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.test("https://example.com/book")); // true
console.log(pattern.exec("https://example.com/books").pathname.groups); // {}
// A group delimiter without a modifier
const pattern = new URLPattern("/book{s}", "https://example.com");
console.log(pattern.pathname); // /books
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.test("https://example.com/book")); // false
// A group delimiter containing a capturing group
const pattern = new URLPattern({ pathname: "/blog/:id(\\d+){-:title}?" });
console.log(pattern.test("https://example.com/blog/123-my-blog")); // true
console.log(pattern.test("https://example.com/blog/123")); // true
console.log(pattern.test("https://example.com/blog/my-blog")); // false
路徑名中的自動組字首
在匹配 URL 的 pathname 部分的模式中,如果組定義前面有斜槓 (/),則組會自動新增斜槓 (/) 字首。這對於帶修飾符的組很有用,因為它允許重複組按預期工作。
如果您不希望自動新增字首,可以透過將組括在組分隔符 ({}) 中來停用它。組分隔符沒有自動新增字首的行為。
// A pattern with an optional group, preceded by a slash
const pattern = new URLPattern("/books/:id?", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // true
console.log(pattern.test("https://example.com/books/")); // false
// A pattern with a repeating group, preceded by a slash
const pattern = new URLPattern("/books/:id+", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books/123/456")); // true
console.log(pattern.test("https://example.com/books/123/")); // false
console.log(pattern.test("https://example.com/books/123/456/")); // false
// Segment prefixing does not occur outside of pathname patterns
const pattern = new URLPattern({ hash: "/books/:id?" });
console.log(pattern.test("https://example.com#/books/123")); // true
console.log(pattern.test("https://example.com#/books")); // false
console.log(pattern.test("https://example.com#/books/")); // true
// Disabling segment prefixing for a group using a group delimiter
const pattern = new URLPattern({ pathname: "/books/{:id}?" });
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // false
console.log(pattern.test("https://example.com/books/")); // true
萬用字元標記
萬用字元標記 (*) 是一個無名捕獲組的簡寫,它匹配所有字元零次或多次。您可以將其放置在模式中的任何位置。萬用字元是貪婪的,這意味著它將匹配最長的可能字串。
// A wildcard at the end of a pattern
const pattern = new URLPattern("/books/*", "https://example.com");
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books")); // false
console.log(pattern.test("https://example.com/books/")); // true
console.log(pattern.test("https://example.com/books/123/456")); // true
// A wildcard in the middle of a pattern
const pattern = new URLPattern("/*.png", "https://example.com");
console.log(pattern.test("https://example.com/image.png")); // true
console.log(pattern.test("https://example.com/image.png/123")); // false
console.log(pattern.test("https://example.com/folder/image.png")); // true
console.log(pattern.test("https://example.com/.png")); // true
路徑名中的尾部斜槓預設不匹配
路徑名中的尾部斜槓不會自動匹配。下面的示例演示了 URLPattern 匹配 /books 的路徑名將匹配 https://example.com/books,但不匹配 https://example.com/books/(反之亦然)。
const patternSlash = new URLPattern({ pathname: "/books/" });
console.log(patternSlash.test("https://example.com/books")); // false
console.log(patternSlash.test("https://example.com/books/")); // true
const patternNoSlash = new URLPattern({ pathname: "/books" });
console.log(patternNoSlash.test("https://example.com/books")); // false
console.log(patternNoSlash.test("https://example.com/books/")); // true
如果您想同時匹配兩者,則需要使用允許兩者之一的匹配模式。最簡單的方法是使用包含正斜槓的組分隔符,後跟可選修飾符。這將匹配帶或不帶終止正斜槓的模式。
const patternOptionalSlash = new URLPattern({ pathname: "/books{/}?" });
console.log(patternOptionalSlash.test("https://example.com/books")); // true
console.log(patternOptionalSlash.test("https://example.com/books/")); // true
模式規範化
解析模式時,它會自動規範化為規範形式。例如,Unicode 字元在路徑名屬性中進行百分比編碼,主機名中使用 punycode 編碼,預設埠號被省略,/foo/./bar/ 等路徑被摺疊為 /foo/bar 等。此外,還有一些模式表示形式解析為相同的底層含義,例如 foo 和 {foo}。這種情況被規範化為最簡單的形式。例如,在這種情況下,{foo} 被規範化為 foo。
從基本 URL 繼承
在 URLPattern 中定義的匹配模式以及在 URLPattern.test() 和 URLPattern.exec() 中使用的測試 URL 都允許輸入指定可選的基本 URL(當將 URL 指定為字串時,此基本 URL 是一個單獨的引數;當將 URL 指定為物件時,它是一個單獨的屬性)。
如果定義了基本 URL,則 URL 部分可能從基本 URL 繼承,並用於設定模式或測試 URL 的部分。URL 解析與您在解析使用基本 URL 指定的 URL 時所期望的非常相似。
username 和 password 永遠不會從基本 URL 繼承。
只有比輸入中定義的最特定部分“更具體”的 URL 部分才會從基本 URL 繼承。以下列表顯示了特異性順序:
protocol(最具體)、hostname、port、pathname、search、hashprotocol、hostname、port、username、password
這意味著,例如,如果在輸入 URL 中指定了 protocol,則沒有更具體的內容,因此不會從基本 URL 繼承任何內容。但是,如果在輸入中指定了 pathname 部分,則 protocol、hostname 和 port 可能會從基本 URL 繼承,但 search 和 hash 不會。
請注意,未在字串/輸入物件中指定或未從基本 URL 繼承的 URL 元件將預設為 URLPattern 的萬用字元值 ("*") 和測試 URL 的空字串 ("")。
區分大小寫
URL 模式 API 在匹配時預設將 URL 的許多部分視為區分大小寫。相比之下,許多客戶端 JavaScript 框架使用不區分大小寫的 URL 匹配。URLPattern() 建構函式上提供了 ignoreCase 選項,如果需要,可以啟用不區分大小寫的匹配。
// Case-sensitive matching by default
const pattern = new URLPattern("https://example.com/2022/feb/*");
console.log(pattern.test("https://example.com/2022/feb/xc44rsz")); // true
console.log(pattern.test("https://example.com/2022/Feb/xc44rsz")); // false
在建構函式中將 ignoreCase 選項設定為 true 會將所有匹配操作切換為給定模式的不區分大小寫匹配。
// Case-insensitive matching
const pattern = new URLPattern("https://example.com/2022/feb/*", {
ignoreCase: true,
});
console.log(pattern.test("https://example.com/2022/feb/xc44rsz")); // true
console.log(pattern.test("https://example.com/2022/Feb/xc44rsz")); // true
示例
過濾特定 URL 元件
以下示例顯示了 URLPattern 如何過濾特定 URL 元件。當使用元件模式的結構化物件呼叫 URLPattern() 建構函式時,任何缺失的元件都預設為 * 萬用字元值。
// Construct a URLPattern that matches a specific domain and its subdomains.
// All other URL components default to the wildcard `*` pattern.
const pattern = new URLPattern({
hostname: "{*.}?example.com",
});
console.log(pattern.hostname); // '{*.}?example.com'
console.log(pattern.protocol); // '*'
console.log(pattern.port); // '*'
console.log(pattern.username); // '*'
console.log(pattern.password); // '*'
console.log(pattern.pathname); // '*'
console.log(pattern.search); // '*'
console.log(pattern.hash); // '*'
console.log(pattern.test("https://example.com/foo/bar")); // true
console.log(pattern.test({ hostname: "cdn.example.com" })); // true
console.log(pattern.test("custom-protocol://example.com/other/path?q=1")); // true
// Prints `false` because the hostname component does not match
console.log(pattern.test("https://cdn-example.com/foo/bar"));
從完整 URL 字串構造 URLPattern
以下示例顯示瞭如何從包含嵌入模式的完整 URL 字串構造 URLPattern。例如,: 既可以是 URL 協議字尾,如 https:,也可以是命名模式組的開頭,如 :foo。如果字元是 URL 語法的一部分還是模式語法的一部分之間沒有歧義,它就會“正常工作”。
// Construct a URLPattern that matches URLs to CDN servers loading jpg images.
// URL components not explicitly specified result in the wild string ("*")
const pattern = new URLPattern("https://cdn-*.example.com/*.jpg");
console.log(pattern.protocol); // 'https'
console.log(pattern.hostname); // 'cdn-*.example.com'
console.log(pattern.pathname); // '/*.jpg'
console.log(pattern.username); // '*'
console.log(pattern.password); // '*'
console.log(pattern.search); // '*'
console.log(pattern.hash); // '*'
// `true`
console.log(
pattern.test("https://cdn-1234.example.com/product/assets/hero.jpg"),
);
// `true` because the search pattern defaults to wildcard
console.log(
pattern.test("https://cdn-1234.example.com/product/assets/hero.jpg?q=1"),
);
構造具有歧義 URL 字串的 URLPattern
以下示例顯示了從歧義字串構造的 URLPattern 如何傾向於將字元視為模式語法的一部分。在這種情況下,: 字元可以是協議元件字尾,也可以是模式中命名組的字首。建構函式選擇將其視為模式的一部分,因此確定這是一個相對路徑名模式。由於沒有基本 URL,因此無法解析相對路徑名,並丟擲錯誤。
// Throws because this is interpreted as a single relative pathname pattern
// with a ":foo" named group and there is no base URL.
const pattern = new URLPattern("data:foo*");
跳脫字元以消除 URLPattern 建構函式字串的歧義
以下示例顯示瞭如何轉義歧義建構函式字串字元以將其視為 URL 分隔符而不是模式字元。這裡 : 被轉義為 \\:。
// Constructs a URLPattern treating the `:` as the protocol suffix.
const pattern = new URLPattern("data\\:foo*");
console.log(pattern.protocol); // 'data'
console.log(pattern.pathname); // 'foo*'
console.log(pattern.username); // '*'
console.log(pattern.password); // '*'
console.log(pattern.hostname); // ''
console.log(pattern.port); // ''
console.log(pattern.search); // '*'
console.log(pattern.hash); // '*'
console.log(pattern.test("data:foobar")); // true
將基本 URL 用於 test() 和 exec()
以下示例顯示了 test() 和 exec() 如何使用基本 URL。
const pattern = new URLPattern({ hostname: "example.com", pathname: "/foo/*" });
console.log(pattern.protocol); // '*'
console.log(pattern.pathname); // '/foo/*'
console.log(pattern.username); // '*'
console.log(pattern.password); // '*'
console.log(pattern.hostname); // 'example.com'
console.log(pattern.port); // '*'
console.log(pattern.search); // '*'
console.log(pattern.hash); // '*'
// `true` as the hostname is inherited from `baseURL` property
// (so is the protocol, but that is matched by the pattern wildcard)
console.log(
pattern.test({
pathname: "/foo/bar",
baseURL: "https://example.com/baz",
}),
);
// Prints `true` as the hostname in the second argument base URL matches.
console.log(pattern.test("/foo/bar", "https://example.com/baz"));
// Throws because the second argument cannot be passed with the object input.
try {
pattern.test({ pathname: "/foo/bar" }, "https://example.com/baz");
} catch (e) {}
// The `exec()` method takes the same arguments as `test()`.
const result = pattern.exec("/foo/bar", "https://example.com/baz");
console.log(result.pathname.input); // '/foo/bar'
console.log(result.pathname.groups[0]); // 'bar'
console.log(result.hostname.input); // 'example.com'
在 URLPattern 建構函式中使用基本 URL
以下示例顯示了基本 URL 也可以用於構造 URLPattern。基本 URL 被嚴格視為 URL,不能包含任何模式語法本身。
該模式僅從基本 URL 繼承比其他屬性中更不具體的 URL 部分。
在這種情況下,指定了 pathname,因此可以繼承協議和主機,但不能繼承搜尋、雜湊、使用者名稱或密碼。未繼承的屬性預設為萬用字元字串 ("*")。例外是埠,它被設定為空字串,因為主機名是從基本 URL 繼承的(它具有隱含的“預設埠”值)。
const pattern1 = new URLPattern({
pathname: "/foo/*",
baseURL: "https://example.com",
});
console.log(pattern1.protocol); // 'https'
console.log(pattern1.hostname); // 'example.com'
console.log(pattern1.pathname); // '/foo/*'
console.log(pattern1.username); // '*'
console.log(pattern1.password); // '*'
console.log(pattern1.port); // ''
console.log(pattern1.search); // '*'
console.log(pattern1.hash); // '*'
// Equivalent to pattern1
const pattern2 = new URLPattern("/foo/*", "https://example.com");
// Throws because a relative constructor string must have a base URL to resolve
// against.
try {
const pattern3 = new URLPattern("/foo/*");
} catch (e) {}
訪問匹配組值
以下示例顯示瞭如何從 exec() 結果物件訪問匹配模式組的輸入值。
input 屬性是與模式匹配的字串:在這種情況下是 cdn.example.com。groups 屬性包含捕獲的組,無名組按數字索引,命名組按名稱索引。在這種情況下,萬用字元屬性只有一個無名組,值為 cdn。
const pattern = new URLPattern({ hostname: "*.example.com" });
const result = pattern.exec({ hostname: "cdn.example.com" });
console.log(result.hostname); // {"groups": {"0": "cdn"}, "input": "cdn.example.com"}
訪問匹配的命名組值
以下示例顯示瞭如何為組指定自定義名稱,這些名稱可用於在結果物件中訪問匹配值。
模式中的匹配模式由 : 符號後跟名稱表示。相同的名稱然後作為鍵出現在 groups 屬性中,匹配值是測試 URL 的匹配部分。input 屬性包含匹配 pathname 模式的 URL 的整個部分。
// Construct a URLPattern using matching groups with custom names.
const pattern = new URLPattern({ pathname: "/:product/:user/:action" });
const result = pattern.exec({ pathname: "/store/wanderview/view" });
console.log(result.pathname);
/*
{
"groups": {
"product": "store",
"user": "wanderview",
"action": "view"
},
"input": "/store/wanderview/view"
}
*/
// These names can then be later used to access the matched values
// in the result object, such as "user" below.
console.log(result.pathname.groups.user); // 'wanderview'
帶無名組的正則表示式
以下示例顯示了匹配組如何使用正則表示式匹配測試 URL 中的 /foo 或 /bar。該組是無名組,因此將透過結果中的索引號進行引用。
const pattern = new URLPattern({ pathname: "/(foo|bar)" });
console.log(pattern.test({ pathname: "/foo" })); // true
console.log(pattern.test({ pathname: "/bar" })); // true
console.log(pattern.test({ pathname: "/baz" })); // false
const result = pattern.exec({ pathname: "/foo" });
console.log(result.pathname.groups[0]); // 'foo'
帶命名組的正則表示式
以下示例顯示瞭如何使用帶命名組的自定義正則表示式。
該組名為 type,匹配 /foo 或 /bar 的路徑。
const pattern = new URLPattern({ pathname: "/:type(foo|bar)" });
const result = pattern.exec({ pathname: "/foo" });
console.log(result.pathname.groups.type); // 'foo'
使匹配組可選
以下示例顯示瞭如何透過在其後放置 ? 修飾符使匹配組可選。
對於路徑名元件,這也導致任何前面的 / 字元被視為組的可選字首。
const pattern = new URLPattern({ pathname: "/product/(index.html)?" });
console.log(pattern.test({ pathname: "/product/index.html" })); // true
console.log(pattern.test({ pathname: "/product" })); // true
const pattern2 = new URLPattern({ pathname: "/product/:action?" });
console.log(pattern2.test({ pathname: "/product/view" })); // true
console.log(pattern2.test({ pathname: "/product" })); // true
萬用字元也可以是可選的。這可能看起來沒有意義,因為它們已經匹配空字串,但它也使路徑名模式中的字首 / 可選。
const pattern3 = new URLPattern({ pathname: "/product/*?" });
console.log(pattern3.test({ pathname: "/product/wanderview/view" })); // true
console.log(pattern3.test({ pathname: "/product" })); // true
console.log(pattern3.test({ pathname: "/product/" })); // true
使匹配組重複
以下示例顯示瞭如何透過在其後放置 + 修飾符使匹配組重複。在 pathname 元件中,這也將 / 字首視為特殊,因此它有效地成為重複組的開頭。
const pattern = new URLPattern({ pathname: "/product/:action+" });
const result = pattern.exec({ pathname: "/product/do/some/thing/cool" });
console.log(result.pathname);
// { "groups": { "action": "do/some/thing/cool" }, "input": "/product/do/some/thing/cool" }
請注意,/product 不匹配,因為它後面沒有 / 和至少一個字元。
console.log(pattern.test({ pathname: "/product" })); // false
console.log(pattern.test({ pathname: "/product/" })); // false
console.log(pattern.test({ pathname: "/product/do" })); // true
console.log(pattern.test({ pathname: "/product/do/" })); // false
使匹配組可選並重復
以下示例顯示瞭如何建立既可選又重複的匹配組。透過在組後放置 * 修飾符來執行此操作。同樣,路徑名元件將 / 字首視為特殊。
它既變為可選,又隨組重複。
const pattern = new URLPattern({ pathname: "/product/:action*" });
const result = pattern.exec({ pathname: "/product/do/some/thing/cool" });
console.log(result.pathname);
// { "groups": { "action": "do/some/thing/cool" }, "input": "/product/do/some/thing/cool" }
請注意,與前面的示例不同,/product 匹配,因為重複的段(包括 /)是可選的。但是,在正斜槓後必須至少有一個字元才能捕獲以匹配重複組。
console.log(pattern.test({ pathname: "/product" })); // true
console.log(pattern.test({ pathname: "/product/" })); // false
console.log(pattern.test({ pathname: "/product/do" })); // true
console.log(pattern.test({ pathname: "/product/do/" })); // false
為可選或重複修飾符使用自定義字首或字尾
以下示例顯示瞭如何將大括號(組分隔符)與命名組一起使用,以表示要由後續 ?、* 或 + 修飾符操作的自定義字首和/或字尾。
例如,{:subdomain.}* 匹配 example.com 的任何子域和域本身。匹配被分配給命名組“subdomain”。
const pattern = new URLPattern({ hostname: "{:subdomain.}*example.com" });
const result = pattern.exec({ hostname: "foo.bar.example.com" });
console.log(pattern.test({ hostname: "example.com" })); // true
console.log(pattern.test({ hostname: "foo.bar.example.com" })); // true
console.log(pattern.test({ hostname: ".example.com" })); // false
console.log(result.hostname);
// { "groups": { "subdomain": "foo.bar" }, "input": "foo.bar.example.com" }
使文字可選或重複而無需匹配組
以下示例顯示瞭如何使用大括號將固定文字值表示為可選或重複,而無需使用匹配組。
以下模式匹配 /product 或 /products/,但由於組分隔符預設不捕獲,因此在相應的匹配組中找不到結果。
const pattern = new URLPattern({ pathname: "/product{/}?" });
console.log(pattern.test({ pathname: "/product" })); // true
console.log(pattern.test({ pathname: "/product/" })); // true
const result = pattern.exec({ pathname: "/product/" });
console.log(result.pathname.groups); // {}
同時使用多個元件和功能
以下示例顯示瞭如何跨多個 URL 元件組合許多功能。
const pattern = new URLPattern({
protocol: "http{s}?",
username: ":user?",
password: ":pass?",
hostname: "{:subdomain.}*example.com",
pathname: "/product/:action*",
});
const result = pattern.exec(
"http://foo:bar@sub.example.com/product/view?q=12345",
);
console.log(result.username.groups.user); // 'foo'
console.log(result.password.groups.pass); // 'bar'
console.log(result.hostname.groups.subdomain); // 'sub'
console.log(result.pathname.groups.action); // 'view'
規範
| 規範 |
|---|
| URL 模式 |
瀏覽器相容性
載入中…
另見
- 在 GitHub 上提供了
URLPattern的 polyfill - URLPattern 使用的模式語法與 path-to-regexp 使用的語法相似