【问题标题】:history.pushState URL interaction with jquery load causing page fetch failure?history.pushState URL 与 jquery 加载的交互导致页面获取失败?
【发布时间】:2020-01-09 11:36:53
【问题描述】:

我使用history.pushState 设置URL,同时使用jquery .load 实际加载页面内容。我是历史 API 的新手,但我知道这是在动态站点中获取后退按钮/等功能的正常方式。

问题是.load 在获取页面时以某种方式使用了我使用pushState 设置的欺骗地址,这意味着.load 正在尝试获取不存在的页面,因此失败。 DocumentRoot 位于服务器上的 /var/www/bar。在此示例中,用户尝试在服务器上的单个 html 文件中的两个点之间导航,该文件位于服务器上 DocumentRoot 下的 dir1/dir2/p1.html

  1. 当用户点击链接1时,服务器应返回dir1/dir2/p1.html #Container1,地址栏应显示foo.com/a/b/c
  2. 当用户点击链接2时,服务器应返回dir1/dir2/p1.html #Container2,地址栏应显示foo.com/a/b/d

那么我到底该怎么做呢?这是我尝试使用相对 URL 的方法,但失败了:

$("#mainContent").load("dir1/dir2/p1.html #container1");  // good: XHR fetch foo.com/bar/dir1/dir2/p1.html
history.pushState(null, null, "a/b/c");                   // good: shows 'foo.com/a/b/c' as the URL
...
$("#mainContent").load("dir1/dir2/p1.html #container2");  // bad: XHR fetch foo.com/bar/a/b/dir1/dir2/p1.html
history.pushState(null, null, "a/b/d");                   // bad: shows 'foo.com/a/b/a/b/d' as the URL

这就是我使用绝对 URL 时发生的情况:

$("#mainContent").load("/dir1/dir2/p1.html #container1");  // good: XHR fetch foo.com/bar/dir1/dir2/p1.html
history.pushState(null, null, "a/b/c");                    // good: shows 'foo.com/a/b/c' as the URL
...
$("#mainContent").load("/dir1/dir2/p1.html #container2");  // bad: XHR fetch foo.com/a/b/dir1/dir2/p1.html
history.pushState(null, null, "a/b/d");                    // good: shows 'foo.com/a/b/d' as the URL

请注意,绝对路径更糟糕,因为 XHR 提取甚至不再使用 DocumentRoot (bar)。谢谢。

编辑 1

在 Chrome/Windows 和 Firefox/Linux 上测试的相对案例,结果相同;绝对案例仅在 Firefox/Linux 上测试。

编辑 2

我一直在尝试并找到两种方法来解决这个问题,但我真的不明白发生了什么,所以我不会发布这个作为答案:

  1. 将所有由history 设置的URL 保持在一级深度,因此a/b/c 变为a-b-c。我在历史 API 上搜索的所有内容都只显示一级深度 URL,所以这可能很常见
  2. base 标签添加到站点的<head> (<base "href=http://example.com/" target="_blank">

【问题讨论】:

  • "请注意,绝对路径更糟糕,因为 XHR 提取甚至不再使用 DocumentRoot (bar)。" - 这不可能。相对 URL(包括具有绝对路径的 URL)由客户端解析。 DocumentRoot 由服务器使用。
  • 您是否将 DocumentRoot 与“原始 HTML 文档的 URL”混淆了?
  • 嗨@Quentin:DocumentRoot 是服务器上httpd.conf 文件中真正的Apache DocumentRoot(我自己写的,我将它设置为/var/www/bar)。上面的 cmets 来自 Firefox 上的客户端控制台日志; XHR 条目实际上在相对情况下显示目录bar,而不是绝对情况下。是的,我也很惊讶。我没想到 Firefox 会知道。
  • 实际上,我想令人困惑的是相对路径显示bar,控制台消息似乎将foo.com等同于/var/www,然后显示foo.com/bar。所以,也许说绝对情况更好会更正确。无论如何,他们都错了。

标签: javascript jquery ajax html5-history


【解决方案1】:

更改历史状态 will change the document's URL 并因此更改其 baseURI 如果没有其他东西已经改变它,例如 <base> 元素。

因此,所有未来的网络请求确实都来自这个新的基础 URI。

要解决此问题,您可以在更改历史状态后手动设置 baseURI,

console.log( document.baseURI ); // /js

history.pushState(null, null, '/foo');
console.log( document.baseURI ); // /foo

// manually set document's baseURI via <base>
const base = document.createElement('base');
base.href = 'bar';
document.head.append(base);
console.log( document.baseURI ); // /bar

As a jsfiddle for users facing StackSnippet's null origined iframes restrictions

或者您甚至可以只在您的文档中从第一个页面加载开始就附加这个 元素一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    相关资源
    最近更新 更多