URL API 是浏览器根据 Whatwg 的标准[https://url.spec.whatwg.org/]实现的一组 API。通常自己去写正则或循环去解析 URL 时,很难考虑全各种边边角角的问题,导致意想不到的错误。而有了这组 API,就可以方便准确地进行 URL 解析了。
URL 的规范可以查看 ietf 的标准[https://tools.ietf.org/html/rfc3986],这里就简单说明一下其组成。
拿这个例子来看:http://www.example.com:8080/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument从前往后依次是
protocol 协议,http:domain name 域名,www.example.comport 端口,8080path 路径,/path/to/myfile.htmlparameters 参数,?key1=value1&key2=value2anchor 锚点,#SomewhereInTheDocumentURL API 的基本用法就把一个 url 的各部分都解析出来。如下:
let u = new URL('http://user:pass@www.example.com:8080/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument') // 会返回包括如下属性的对象 // hash: "#SomewhereInTheDocument" // host: "www.example.com" // hostname: "www.example.com" // href: "http://www.example.com/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument" // origin: "http://www.example.com" // password: "pass" // pathname: "/path/to/myfile.html" // port: "8080" // protocol: "http:" // search: "?key1=value1&key2=value2" // username: "user"这样就可以得到 url 中对应的各个部分。
这里面需要注意的一点是,如果给这些属性设置新的值,那么同时 href 的值也会对应改变。
console.log(u.href) // 'http://user:pass@www.example.com:8080/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument' u.port = 9090 console.log(u.href) // 'http://user:pass@www.example.com:9090/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument'URL 对象除了上述所示属性外,还提供了 searchParams 属性,这个属性是一个 URLSearchParams 对象,在这个对象上可以访问如下方法:append(), delete(), entries(), forEach(), get(), getAll(), has(), keys(), set(), sort(), toString(), values()。这里面常用的就是 get, set, keys, values 等,这些方法作用和字面意思一样,然后我们就以例子来理解一下。
u.searchParams.get('key1') // "value1" u.searchParams.getAll('key1') // ["value1"] 返回所有 key 为 "key1" 的 value 组成的数组。 u.searchParams.has('kkk') // false 是否包含 key 等于 “kkk” u.searchParams.toString() // "key1=value1&key2=value2&key1=value1" u.searchParams.forEach((value, key) => { // 跟数组 forEach 类似 console.log(key, value) // key1, value1 // key2, value2 // ... }) let entriesIter = u.searchParams.entries() // 返回一个 entries 的 Iterator for (let entry of entriesIter) { console.log(entry) // ["key1", "value1"] // ["key2", "value2"] // ... } let keysIter = u.searchParams.keys() // 返回一个 keys 的 Iterator for (let key of keysIter) { console.log(key) // "key1" // "key2" // ... } let valuesIter = u.searchParams.values() // 返回一个 values 的 Iterator for (let value of valuesIter) { console.log(value) // "value1" // "value2" // ... } u.searchParams.sort() // 和数组方法一样,会改变原数据 u.searchParams.toString() // "key1=value1&key1=value1&key2=value2" u.searchParams.set('key1', 'newValue1') // 改变 key1 的值为 “newValue1” u.searchParams.delete('key1') // 会删掉所有 key 为 key1 的项 u.searchParams.append('key1', 'value1') // 会增加一项 key1=value1,不管是否存在 key1=value1,都会增加一个新项,不会修改之前存在的key和value上面这些方法中 append, delete, set, sort 都会修改原数据,这些改变也都实时表现到 href 属性上。
除了上述对 URL 的解析操作外,URL.createObjectURL() 有时我们也会使用到,比如预览本地图片;通过 Ajax 去下载文件等。它的作用是可以把一个 File,Blob,MediaSource 对象变成一个 URL 字符串,通过这个 URL 浏览器可以访问到原对象。另外需要注意,生成的 URL 的有效期是和 document 绑定的,所以当你使用完之后,一定记得把这部分内容从内存中释放。对应释放的方法为URL.revokeObjectURL()。
我这里截取 mdn[https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images] 上一个例子的一部分代码,来简单说明一下:
const img = document.createElement("img"); img.src = URL.createObjectURL(file); // 这里 file 是一个 File 对象 img.height = 60; img.onload = function() { URL.revokeObjectURL(this.src); // 在图片加载完之后,不需要再访问这个图片,就从内存中释放掉 }URL 部分其实还涉及到一些序列化、转码等问题,这些问题先记下来,之后有时间整理一下。
