使用JavaScript将相对路径转换为绝对路径

Jas*_*per 56 html javascript path

有一个功能,它给我的网址如下:

./some.css
./extra/some.css
../../lib/slider/slider.css
Run Code Online (Sandbox Code Playgroud)

它始终是一条相对的道路.

让我们知道我们知道页面的当前路径,比如http://site.com/stats/2012/,不确定如何将这些相对路径转换为真实路径?

我们应该得到类似的东西:

./some.css => http://site.com/stats/2012/some.css
./extra/some.css => http://site.com/stats/2012/extra/some.css
../../lib/slider/slider.css => http://site.com/lib/slider/slider.css
Run Code Online (Sandbox Code Playgroud)

没有jQuery,只有vanilla javascript.

Ela*_*lad 74

最简单,有效和正确的方法,只使用URL api.

new URL("http://www.stackoverflow.com?q=hello").href;
//=> http://www.stackoverflow.com/?q=hello"

new URL("mypath","http://www.stackoverflow.com").href;
//=> "http://www.stackoverflow.com/mypath"

new URL("../mypath","http://www.stackoverflow.com/search").href
//=> "http://www.stackoverflow.com/mypath"

new URL("../mypath", document.baseURI).href
//=> "https://stackoverflow.com/questions/mypath"
Run Code Online (Sandbox Code Playgroud)

性能方面,此解决方案与使用字符串操作相同,速度是创建a标记的两倍.

  • @hex你是对的,使用`window.location.href`有这个缺点。我已经编辑了答案,使其使用“document.baseURI”代替。 (3认同)
  • 喜欢这个解决方案,但由于缺乏或URL支持,无法使用React Native.相反,我使用[https://www.npmjs.com/package/url ](https://www.npmjs.com/package/url),效果很好. (2认同)

all*_*kim 65

Javascript会为你做的.无需创建功能.无需设置basename.

var link = document.createElement("a");
link.href = "../../lib/slider/slider.css";
alert(link.protocol+"//"+link.host+link.pathname+link.search+link.hash);

// Output will be "http://www.yoursite.com/lib/slider/slider.css"
Run Code Online (Sandbox Code Playgroud)

如果你需要一个函数,只需将它包装为一个包含3行代码的函数.

var absolutePath = function(href) {
    var link = document.createElement("a");
    link.href = href;
    return (link.protocol+"//"+link.host+link.pathname+link.search+link.hash);
}
Run Code Online (Sandbox Code Playgroud)

----更新---
只有在需要绝对路径时才能使用更简单的版本

var absolutePath = function(href) {
    var link = document.createElement("a");
    link.href = href;
    return link.href;
}
Run Code Online (Sandbox Code Playgroud)

  • 这在IE中不起作用,甚至IE11也不行.有关详细信息,请参阅此处:http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue (4认同)
  • 很好,但只能在浏览器中使用,我认为OP不需要.. (2认同)
  • 工作得很好(在IE中也是如此)......我发现只需在设置后访问`link.href`就会返回已解析的URL(即,无需手动重建href). (2认同)

Ber*_*rgi 38

这应该这样做:

function absolute(base, relative) {
    var stack = base.split("/"),
        parts = relative.split("/");
    stack.pop(); // remove current file name (or empty string)
                 // (omit if "base" is the current folder without trailing slash)
    for (var i=0; i<parts.length; i++) {
        if (parts[i] == ".")
            continue;
        if (parts[i] == "..")
            stack.pop();
        else
            stack.push(parts[i]);
    }
    return stack.join("/");
}
Run Code Online (Sandbox Code Playgroud)

  • 对于以后遇到此问题的任何人,使用 document.location.href 作为 base 对我有用。 (2认同)
  • 当相对 url 以 `/` 例如 `/some.css` 开头时,此解决方案会出现问题。在这种情况下,正确的实现将删除堆栈中域名后的所有项目。 (2认同)

mad*_*phy 6

这来自MDN是牢不可破的!

/*\
|*|
|*|  :: translate relative paths to absolute paths ::
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*|
|*|  The following code is released under the GNU Public License, version 3 or later.
|*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/

function relPathToAbs (sRelPath) {
  var nUpLn, sDir = "", sPath = location.pathname.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, "$1"));
  for (var nEnd, nStart = 0; nEnd = sPath.indexOf("/../", nStart), nEnd > -1; nStart = nEnd + nUpLn) {
    nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length;
    sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp("(?:\\\/+[^\\\/]*){0," + ((nUpLn - 1) / 3) + "}$"), "/");
  }
  return sDir + sPath.substr(nStart);
}
Run Code Online (Sandbox Code Playgroud)

样品用法:

/* Let us be in /en-US/docs/Web/API/document.cookie */

alert(location.pathname);
// displays: /en-US/docs/Web/API/document.cookie

alert(relPathToAbs("./"));
// displays: /en-US/docs/Web/API/

alert(relPathToAbs("../Guide/API/DOM/Storage"));
// displays: /en-US/docs/Web/Guide/API/DOM/Storage

alert(relPathToAbs("../../Firefox"));
// displays: /en-US/docs/Firefox

alert(relPathToAbs("../Guide/././API/../../../Firefox"));
// displays: /en-US/docs/Firefox
Run Code Online (Sandbox Code Playgroud)

  • 它不处理具有前导`/`的相对路径.示例:`relPathToAbs("/?foo = bar")`应返回"/?foo = bar"而不是返回`/ questions/14780350 /?foo = bar`,这意味着它在发送时没有正确检测到前导`/`返回根目录的路径. (2认同)

opt*_*tor 5

如果要从浏览器中的自定义网页(而不是运行脚本的页面)对链接进行相对绝对转换,则可以使用@Bergi建议的功能的更高版本:

var resolveURL=function resolve(url, base){
    if('string'!==typeof url || !url){
        return null; // wrong or empty url
    }
    else if(url.match(/^[a-z]+\:\/\//i)){ 
        return url; // url is absolute already 
    }
    else if(url.match(/^\/\//)){ 
        return 'http:'+url; // url is absolute already 
    }
    else if(url.match(/^[a-z]+\:/i)){ 
        return url; // data URI, mailto:, tel:, etc.
    }
    else if('string'!==typeof base){
        var a=document.createElement('a'); 
        a.href=url; // try to resolve url without base  
        if(!a.pathname){ 
            return null; // url not valid 
        }
        return 'http://'+url;
    }
    else{ 
        base=resolve(base); // check base
        if(base===null){
            return null; // wrong base
        }
    }
    var a=document.createElement('a'); 
    a.href=base;

    if(url[0]==='/'){ 
        base=[]; // rooted path
    }
    else{ 
        base=a.pathname.split('/'); // relative path
        base.pop(); 
    }
    url=url.split('/');
    for(var i=0; i<url.length; ++i){
        if(url[i]==='.'){ // current directory
            continue;
        }
        if(url[i]==='..'){ // parent directory
            if('undefined'===typeof base.pop() || base.length===0){ 
                return null; // wrong url accessing non-existing parent directories
            }
        }
        else{ // child directory
            base.push(url[i]); 
        }
    }
    return a.protocol+'//'+a.hostname+base.join('/');
}
Run Code Online (Sandbox Code Playgroud)

null如果出现问题,它会返回.

用法:

resolveURL('./some.css', 'http://example.com/stats/2012/'); 
// returns http://example.com/stats/2012/some.css

resolveURL('extra/some.css', 'http://example.com/stats/2012/');
// returns http://example.com/stats/2012/extra/some.css

resolveURL('../../lib/slider/slider.css', 'http://example.com/stats/2012/');
// returns http://example.com/lib/slider/slider.css

resolveURL('/rootFolder/some.css', 'https://example.com/stats/2012/');
// returns https://example.com/rootFolder/some.css

resolveURL('localhost');
// returns http://localhost

resolveURL('../non_existing_file', 'example.com')
// returns null
Run Code Online (Sandbox Code Playgroud)