首页 > 解决方案 > 是否可以阻止 window.history pushstate() 向服务器发送 URL 请求?

问题描述

我正在制作一个单页网页。

我已经设置了一个 node.js 服务器,并且我已经完成了它,以便它可以确定来自用户的请求是 URL 还是资源请求。

当用户第一次加入时,我向他们发送 index.html 文件,然后请求 css、图像和 javascript。(这些都是骨架文件...例如,带有链接但不是实际内容的网站主要布局的文件)在客户端javascript上,我有代码查看用户所在的URL,然后发送一个向服务器请求更多 html 或 css,到目前为止一切都很好。

但是,当我使用 window.history.pushstate() 更新 URL 时(用户点击<a>标签,我已阻止默认),它会向服务器发送一个请求,告诉用户他们已经更改了 URL,这是我不想要的。这是因为客户端 javascript 应该发送资源请求,以便它可以在不刷新的情况下更新页面。

在我的服务器上,我不相信有办法判断客户端是否已经拥有 index.html,因此当它收到 URL 请求时,它不知道是否发送 index.html 文件(这会导致页面刷新)。

我想知道是否有一种方法可以阻止 pushstate() 告诉服务器用户已更改 url(因为它不是必需的),或者有一种方法可以知道用户是否已经拥有 index.html 文件。

我知道这应该考虑诸如用户在多个不同的选项卡上打开网页(并且应该为每个单独的选项卡发送 index.html)或手动更改 url 的情况。

如果服务器必须接收 URL 请求,我的想法是使用 remoteAddress 和 remotePort 属性并以某种方式存储它们,然后在用户发送请求时比较它们。(假设新选项卡将使用不同的远程端口)。

抱歉,我无法包含任何代码,因为我目前正在手机上输入这个,所以我不会在早上忘记这篇文章。我没有将 express.js 与 node.js 一起使用,因为我想在使用抽象模块之前知道下面发生了什么。除了前端的 javascript 和 jquery 之外,我没有使用任何其他框架。后端的纯节点。

这不一定是代码请求,因为我很乐意编写自己的代码,我只需要有关如何处理此问题的建议。

标签: javascriptnode.jshttpsingle-page-applicationhtml5-history

解决方案


所以,事实证明,我从来没有真正调用过调用推送历史的函数。下面是我的客户端代码(工作正常),以防万一将来有人遇到这样的愚蠢问题。

const main_page = ["/", "/index.html", "/home"];

const main_err = {
    403: "FORBIDDEN", 
    404: "PAGE NOT FOUND"
};
const sub_err = {
    403: "Your request has been denied by the server.",
    404: "It looks like that page doesn't exist."
};

function get_error_message(status_num, html_request) {
    if (!html_request) {return status_num};
    return `<style>
        .main-body {font-family: Arial}
        .main-body h6 {font-size: 14px;font-weight: lighter;margin: 0 0 5px 0;}
        .main-body h1 {font-size: 30px;margin: 0 0 12px 0;}
        .main-body h4 {font-size: 18px;font-weight: lighter;margin: 0;}
    </style>
    <h6>${main_err[status_num]}<h4>
    <h1>${status_num}</h1>
    <h4>${sub_err[status_num]}</h3>`;
};

function make_request(url, html_request, callback) {
    let req = new XMLHttpRequest();
    req.onreadystatechange = function() {
        if (req.readyState === 4) {
            if (req.status === 200) {callback(req.responseText, true)} 
            else {callback(get_error_message(req.status, html_request), false)}}
        }
    req.open("GET", url);req.send();
}

function update_body(html) {document.getElementsByClassName("main-body")[0].innerHTML = html};

function nav_buttons(new_button) {
    window.scrollTo(0, 0);
    $(".main-link .active, .category-link .active").attr("class", "inactive");
    $(new_button).attr("class", "active");
}

window.addEventListener('popstate', function(event) {
    let data_passed = event.state
    make_request(data_passed[0], true, update_body)
    nav_buttons(data_passed[1])
    window.scrollTo(0, 0)
});

function navBarButtonClicked() {
    $(".main-link, .category-link").click(function(event) {
        event.preventDefault()
        let href = $(this).attr("href");
        href = ((!main_page.includes(href)) ? href : "/home").substring(1);
        let html_page = "assets/static/pages/"+href+".html"
        console.log("REQUESTED PAGE:" + html_page)
        make_request(html_page, true, update_body)
        let id_of_element = "#" + $("> div", this).attr("id")
        history.pushState([html_page, id_of_element], null, `/${href}`);
        document.title = href
        nav_buttons(id_of_element)
    });
};

function __main__() {
    let href = window.location.pathname;
    href = ((!main_page.includes(href)) ? href : "/home").substring(1);
    document.title = href; //check if valid route in future
    let page_location = `assets/static/pages/${href}.html`
    history.replaceState([page_location, `#header-${href}`], "", `/${href}`);
    nav_buttons(`#header-${href}`)
    make_request(page_location, true, update_body)
    navBarButtonClicked();
};

__main__();

推荐阅读