node:url
对于路径:https://user:pass@xxx.com:8000/p/a/t/h?q=s#foo
各个部分的命名如下
| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|` https:` | `//` | `user` | `:` | `pass` | `@` | `xxx.com` | `:` | `8000` | `/p/a/t/h` | `?` | `q=s` | `#foo` |
| protocol | | username | | password | | hostname | | port | pathname | | query | hash |
| || auth ||| | host ||| | search || |
| origin ||||||||| path ||| |
| href |||||||||||URL
在 Nodejs 中可以直接使用 URL 进行实例化,实际上它是从 url 模块中暴露出来的,
import url from 'node:url'
console.log(url.URL === URL)
// true可以用 new URL 或者 url.parse 来得到一个 URL 实例,他们产生的结果略有不同,各有一些独特的字段
import { url, URL} from 'node:url';
new URL('https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash')
/*
URL {
href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash',
host: 'sub.example.com:8080',
hostname: 'sub.example.com',
search: '?query=string',
pathname: '/p/a/t/h',
protocol: 'https:',
hash: '#hash'
port: '8080',
origin: 'https://sub.example.com:8080', // only
username: 'user', // only
password: 'pass', // only
searchParams: URLSearchParams { 'query' => 'string' }, // only
}
*/
url.parse('https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash');
/*
Url {
href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash'
host: 'sub.example.com:8080',
hostname: 'sub.example.com',
search: '?query=string',
pathname: '/p/a/t/h',
protocol: 'https:',
hash: '#hash',
port: '8080',
slashes: true, // only
auth: 'user:pass', // only
query: 'query=string', // only
path: '/p/a/t/h?query=string', // only
}
*/TIP
推荐使用 new URL 而不是 url.parse,searchParams 可以对查询参数进行丰富的操作
URLSearchParams
URLSearchParams 这个构造函数在 NodeJS/Browser 环境都是全局存在的,但不完全一致,比如 .size 属性,NodeJs 支持的比较晚
初始化
带不带 ? 都是等价的,可以直接传入 search 或者 query 字符串
const params = new URLSearchParams('?foo=1')
const params = new URLSearchParams('foo=1')添加数据
有两个方法可以写入数据:append 和 set,append 只会追加数据,而 set 会覆盖全部如果存在的键
params.append('bar', '1')
params.append('bar', '2')
console.log(params.toString()) //=> bar=1&bar=2
params.set('bar', '3')
console.log(params.toString()) //=> bar=3删除数据
通过 delete 方法来删除数据,delete 会删除全部如果存在的键
params.append('bar', '1')
params.append('foo', '2')
console.log(params.toString()) //=> bar=1&foo=2
params.delete('bar')
console.log(params.toString()) //=> foo=2获取数据
获取数据的方式就非常丰富了,包括 get/getAll/keys/values/entries,还有方便遍历的 forEach 方法
params.append('bar', '1')
params.append('bar', '2')
console.log(params.get('bar')) //=> 1
console.log(params.getAll('bar')) //=> ['1', '2']
console.log(params.keys()) //=> URLSearchParams Iterator { 'bar', 'bar' }
console.log(params.values()) //=> URLSearchParams Iterator { '1', '2' }
console.log(params.entries())
//=> URLSearchParams Iterator { [ 'bar', '1' ], [ 'bar', '2' ] }其他方法
方法 has 用于判断键是否存在,sort 用于按照键名排序(很遗憾不支持自定义排序),需要注意的是 append 方法在添加元素的时候就会自动排序,所以 sort 一般用于给 URLSearchParams 初始化的参数排序
const params = new URLSearchParams('foo=2&bar=3')
console.log(params.has('foo'))
console.log(params.toString()) //=> foo=2&bar=3
params.sort()
console.log(params.toString()) //=> bar=3&foo=2Unicode/ASCII
自带了对域名进行字符的转换的方法
import url from 'node:url';
console.log(url.domainToASCII('español.com'));
// Prints xn--espaol-zwa.com
console.log(url.domainToASCII('中文.com'));
// Prints xn--fiq228c.com
console.log(url.domainToUnicode('xn--espaol-zwa.com'));
// Prints español.com
console.log(url.domainToUnicode('xn--fiq228c.com'));
// Prints 中文.comFileUrl 🔄 Path
在处理路径的时候,最常用的两个函数
import { fileURLToPath, pathToFileURL } from 'url'
const currentUrl = import.meta.url
console.log(currentUrl)
// file:///path/to/your/project/app.ts
console.log(fileURLToPath(currentUrl))
// /path/to/your/project/app.ts
console.log(pathToFileURL(fileURLToPath(currentUrl)).href)
// file:///path/to/your/project/app.ts可以用 fileURLToPath 在 ESM 中得到 __dirname 和 __filename
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);