如何在 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 错误。
我想写一个简单的 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 错误。