對于一名前端工程??來說,解析url這種操作是衡量是否合格的標(biāo)準(zhǔn)之一。今天,就來探討幾種神奇的解析方法。
(一)a標(biāo)簽自動(dòng)解析URL
var a = document.createElement('a');
a.;
var div = document.createElement('div');
for (var key in a) {
!(key in div) && !!a[key] && console.log(`${key} = ${a[key]}`);
}
輸出結(jié)果如下所示:
relList =
href = http://www.example.com/news.php?id=10#footer
origin = http://www.example.com
protocol = http:
host = www.example.com
hostname = www.example.com
pathname = /news.php
search = ?id=10
hash = #footer
這些都是a標(biāo)簽特有的屬性,且a標(biāo)簽的該屬性有值,也就是說,a標(biāo)簽自動(dòng)完成了URL解析,對于前端來說,這曾經(jīng)是解析URL最廉價(jià)的方式,如下為更加健壯的通用方法:
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return {
source: url,
protocol: a.protocol.replace(':',''),
host: a.hostname,
port: a.port,
query: a.search,
params: (function(){
var ret = {},
seg = a.search.replace(/^\?/,'').split('&'),
len = seg.length, i = 0, s;
for (;i<len;i++) {
if (!seg[i]) { continue; }
s = seg[i].split('=');
ret[s[0]] = s[1];
}
return ret;
})(),
file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
hash: a.hash.replace('#',''),
path: a.pathname.replace(/^([^\/])/,'/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
segments: a.pathname.replace(/^\//,'').split('/')
};
}
該方法絕對可靠
(二)JS URL API
var url = new URL('http://www.example.com:$88;9,9@www.abc.com$/what??key=val?&{http://?query=2#45');
for (var key in url) {
console.log(`${key} = ${url[key]}`);
}
Chrome下輸出結(jié)果:
"href = http://www%2Eexample%2Ecom:$88%3B9,9@www.abc.com$/what??key=val?&{http://?query=2#45"
"origin = http://www.abc.com$"
"protocol = http:"
username = www%2Eexample%2Ecom
password = $88%3B9,9
host = www.abc.com$
hostname = www.abc.com$
port =
pathname = /what
search = ??key=val?&&
searchParams = %3Fkey=val%3F
hash = #123http://?query=2#45
如要獲得hostname,有如下方法:
var getHostname = function(url) {
return new URL(url).hostname;
};
該方法目前只有部分瀏覽器支持,兼容情況請查閱:https://developer.mozilla.org/zh-CN/docs/Web/API/URL/URL
(三)神級操作正則解析
var parseUrl = function(url) {
var urlParseRE = /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/;
var matches = urlParseRE.exec(url || "") || [];
return {
href: matches[0] || "",
hrefNoHash: matches[1] || "",
hrefNoSearch: matches[2] || "",
domain: matches[3] || "",
protocol: matches[4] || "",
doubleSlash: matches[5] || "",
authority: matches[6] || "",
username: matches[8] || "",
password: matches[9] || "",
host: matches[10] || "",
hostname: matches[11] || "",
port: matches[12] || "",
pathname: matches[13] || "",
directory: matches[14] || "",
filename: matches[15] || "",
search: matches[16] || "",
hash: matches[17] || ""
};
};
解讀:
/^ #href
\s*
( #hrefNoHash
( #hrefNoSearch
( #domain
([^:\/#\?]+:)? #protocol
(?:
(\/\/) #doubleSlash
( #authority
(?:
( #取結(jié)果時(shí)$7被跳過了,應(yīng)該也用非捕獲型括號(?:
([^:@\/#\?]+) #username
(?:
\:
([^:@\/#\?]+) #password
)?
)
@
)?
( #host
([^:\/#\?\]\[]+|\[[^\/\]@#?]+\]) #hostname
(?:
\:
([0-9]+) #port
)?
)
)?
)?
)?
( #pathname
(\/?(?:[^\/\?#]+\/+)*) #directory
([^\?#]*) #filename
)
)?
(\?[^#]+)? #search
)
(#.*)? #hash
/
具體自行領(lǐng)會~