如何在Javascript中设置页面的基础href?

38

我希望能够通过JavaScript基于当前主机名设置页面的base href属性。我生成的HTML页面可以在不同的主机名上查看,这意味着生成base href标签将在一个主机名上工作,但在另一个主机名上将不正确。


我通常有一个常量JS文件,其中我设置$.serverRoot为主机的相对根目录(例如$.serverRoot = '/myapp/';),并将其包含在内。 - Bob Fincheimer
这对于像 AJAX 请求之类的东西很有效,但是如果我要调整所有图像路径和链接 href 来考虑 JavaScript 变量,我将不得不做大量的工作。使用基本 href 标签解决了我在不同主机名上访问相同 HTML 文件时遇到的许多问题,但它引入了一个在一个主机名上路径不正确的问题。 - Zach Gardner
5个回答

44

正确的方法是根据当前主机名使用document.write编写标签:

正确的方法:

<script type="text/javascript">
document.write("<base href='http://" + document.location.host + "' />");
</script>

这个方法在IE、FF、Chrome和Safari浏览器中都能正确产生结果。它和以下做法产生了一个(正确的)不同的结果:

错误的做法:

<script type="text/javascript">
var newBase = document.createElement("base");
newBase.setAttribute("href", document.location.hostname);
document.getElementsByTagName("head")[0].appendChild(newBase);
</script>

12
没有任何理由证明document.write是“正确”的,而将节点正确插入文档树则是“错误”的。这个问题属于“解决错误问题”的范畴,但这里描述的方法通常会在错误的位置插入base标签。如果代码位于head部分,这样做是无用的(为什么不像普通HTML一样放置正确的base标签?),而如果在其他位置执行,则通常会将base插入到body中。 - Jukka K. Korpela
4
“错误”的方法实际上并不起作用。让浏览器动态更改其基本 href 的唯一方法是使用“正确”的方法。 - Zach Gardner
3
你好!根据我在启用Angular的网页上的测试,document.write模式似乎要等到太晚才添加基础标签。我已经比较了通过JavaScript添加和硬编码到标记中时的标记,它们看起来相同,但是JavaScript解决方案没有应用任何基础标签功能,尽管“看起来”已经就位了...有什么想法吗? - Jesper Wilfing
12
“http:”不应该改成“document.location.protocol”吗? - Tom
3
我发现在初始加载时,即使document.write在样式表链接和其他资源之前,Chrome仍然首先查找原始URL的文件,然后再尝试使用<base/>的内容进行访问。例如,如果我的原始URL是http://site.dev/account,而document.write的结果将base设置为http://site.dev/,这些资源会首先尝试从/account/加载,服务器返回404错误,然后才能从http://site.dev/正确加载。 - nickford
显示剩余3条评论

14

我认为你最好这样做。

    <script type="text/javascript">
        document.head.innerHTML = document.head.innerHTML + "<base href='" + document.location.href + "' />";
    </script>

location.hostname无法返回应用程序上下文根!您还可以在控制台上使用console.log记录document.location,以查看有关document.location的所有可用元数据。


2
现在这种方式更加合适(而不是使用 document.write)。实际上,就实用性而言:在 jsFiddle 中,这种方式对我有效,而 document.write 则无效。 - YakovL

6

我不同意前面的答案。因为它没有考虑到协议,所以会失败。

我提供了一个可行的解决方案来考虑协议/主机名/端口,具体如下:

    var base = document.createElement('base');
    base.href = window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : '');
    document.getElementsByTagName('head')[0].appendChild(base);

目前在包括IE11在内的所有主要浏览器中都可以正常使用。

我已经使用它来制作了一个npm包,如果有人感兴趣,还支持在这个基础href的末尾添加后缀。

https://www.npmjs.com/package/dynamic-base

https://github.com/codymikol/dynamic-base


2

<script>
document.write("<base href='"+ window.location.protocol +'//' + window.location.host + "' >");
</script>


0
window.document.head.innerHTML=`<base href=${href}>`+window.document.head.innerHTML;

href变量是您想要使用的链接。


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接