如何在 javascript 中实现基本的 angular 类路由

How to implement basic angular-like routing in plain javascript

我想写一个简单的 javascript 实现类似 Angular 的路由,但我不知道该怎么做。假设我有一个索引页面,我想通过 <a href="Index/2">Navigate Like in Angular</a> 导航到 Index/2 ,但阻止将请求发送到服务器,而是获取一些我可以处理的事件。我试过像这样使用 beforeunload 事件

<script>
        window.onbeforeunload = function (ev) {
 
            ev.preventDefault();
            return '';
        };
 
    </script>

但这种方法行不通。首先,它显示一条我不感兴趣的弹出消息,其次,如果我按取消,浏览器地址控件中的 url 仍然是“http://.../Index”,我不不知道有什么方法可以“悄悄”修改为“http://.../Index/2”。 任何帮助将不胜感激。

---更新---

如果有人需要,这里是 Angular 类 (SPA) 路由的最小实现,感谢 Quentin

Index.html,托管在静态网站:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <button title="navigate without request to server" routing-link="/Index/2">Navigate 2</button>
    <button title="navigate without request to server" routing-link="/Index/3">Navigate 3</button>

    <div id="outlet"></div>
    
    <script>

        function updateRoute(){ 
            
            relativeUrl = location.href.substring(location.origin.length + 1, location.href.length);
            document.getElementById("outlet").innerHTML = relativeUrl + ", " + history.length;
        }

        window.addEventListener("click", ev => {

            let routingLink = ev.target.attributes && ev.target.attributes['routing-link'];

            if (routingLink && relativeUrl != routingLink.value) {
                
                history.pushState({ relativeUrl: routingLink.value }, "", location.origin + '/' + routingLink.value);
                updateRoute();
            }
        });

        window.addEventListener("popstate", ev => {

            updateRoute()
        });

        
        let relativeUrl = "";
        
        updateRoute();
                
    </script>

</body>
</html>

如果你和我一样使用IIS作为主机,别忘了安装“URL Rewrite”模块,复制下面的web.config 到站点的根目录:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="./Index.html" />
      </rule>
    </rules>
  </rewrite>
  </system.webServer>
</configuration>

这将处理仍然向服务器发送请求的情况,例如由于浏览器刷新。

你不能拦截浏览器离开页面来实现这个。

您需要有一个 click 事件侦听器来捕获正在激活的 link。

然后您可以防止默认行为,随心所欲地修改 DOM,然后使用 the History API.

操纵 URL

您还需要处理 popState events 以便后退按钮继续工作。


请记住,当浏览器要求将新的 URL 作为 SPA 的入口点时,您确实需要让服务器提供一些有用的东西,而这最好由服务器端提供您的应用程序的渲染版本。

一种更黑客的方法是只提供一些框架 HTML 和 bootstrap 所有带有客户端 JS 的东西……但是你 运行 会遇到确定服务器何时应该报告错误的问题404 错误。