【发布时间】:2022-02-13 23:06:50
【问题描述】:
我正在使用纯 Javascript + express-JS 构建一个单页应用程序。我有两个链接到两个锚链接的视图,以便我可以在视图之间切换。问题是,其中一个视图(默认视图)显示 d3 图表,并且仅在站点最初加载或页面刷新时才显示它。如果我只是单击它自己的锚链接,理论上它应该什么都不做并且仍然显示图表,但图表消失了,但与该视图对应的所有其他 html 元素都保留了。我确保在我的所有内容都被加载后,该文件的脚本标记被加载到基本 html 文件中,但问题仍然存在。有人能指出这里出了什么问题吗?
var tag = document.createElement("script");
function scriptLoad() {
tag.src = "static/js/d3chart.js";
tag.id = "d3chart"
document.getElementsByTagName('head')[0].appendChild(tag);
};
document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener("click", e => {
if (e.target.matches("[data-link]")) {
e.preventDefault();
navigateTo(e.target.href);
}
scriptLoad();
});
router();
});
基本 html 文件中的 HTML 锚链接
<a href="/" data-link>View 1</a>
<a href="/view2" data-link>View 2</a>
完整代码
import view1 from "./views/view1.js"
import view2 from "./views/view2.js"
const pathToRegex = path => new RegExp("^" + path.replace(/\//g, "\\/").replace(/:\w+/g, "(.+)") + "$");
const getParams = match => {
const values = match.result.slice(1);
const keys = Array.from(match.route.path.matchAll(/:(\w+)/g)).map(result => result[1]);
return Object.fromEntries(keys.map((key, i) => {
return [key, values[i]];
}));
};
const navigateTo = url => {
history.pushState(null, null, url);
router();
};
const router = async () => {
const routes = [
{ path: "/", view: view1 },
{ path: "/view2", view: view2 }
];
// Test each route for potential match
const potentialMatches = routes.map(route => {
return {
route: route,
result: location.pathname.match(pathToRegex(route.path))
};
});
let match = potentialMatches.find(potentialMatch => potentialMatch.result !== null);
if (!match) {
match = {
route: routes[0],
result: [location.pathname]
};
}
const view = new match.route.view(getParams(match));
document.querySelector("#app").innerHTML = await view.getHtml();
};
window.addEventListener("popstate", router);
var tag = document.createElement("script");
function scriptLoad () {
tag.src = "static/js/d3chart.js";
tag.id = "d3chart"
document.getElementsByTagName('body')[0].appendChild(tag);
}
document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener("click", e => {
if (e.target.matches("[data-link]")) {
e.preventDefault();
navigateTo(e.target.href);
}
scriptLoad();
});
router();
});
view1.js 文件 - 开始时的默认视图(图表视图)
import AbstracView from "./AbstractView.js"
export default class extends AbstracView {
constructor() {
super();
this.setTitle("D3 Chart - View1");
}
async getHtml() {
return `
<h1>D3 Chart</h1>
<div class="chart-area"></div>
`;
}
}
【问题讨论】:
-
您正在单击侦听器内部执行
scriptLoad()函数,它应该在外部完成,否则,每次单击时您都在重新加载同一个文件,这似乎是您的问题。 -
我把它放在外面,它不起作用。我也在使用 History API,这是否会导致这种情况?此外,最初,当我在基本 html 文件中包含脚本标记时,图表甚至没有在启动或刷新时加载。一旦我确定在加载内容后插入了脚本标签,图表就会显示出来,但是当我点击它自己的锚链接时它就会消失
-
我认为它与 History API 无关,但这可能取决于您在
navigateTo函数中所做的事情。可以肯定的是,您将scriptLoad移到了click侦听器之外,但您将它保留在DOMContentLoaded侦听器中,对吗?如果是这样,请向我们展示您的其余代码,例如模板和navigateTo函数的内容。 -
我已经用其余的代码更新了我的问题。让我知道您是否需要查看其他内容。是的,我在
DOMContentLoaded侦听器内但在click侦听器之外调用了scriptLoad();函数。我在router();函数调用的正上方调用它。 -
script没有直接加载到 HTML 文件中是否有任何原因?
标签: javascript html express single-page-application