JS无法在加载.load的页面上执行

时间:2018-12-10 00:19:09

标签: javascript jquery single-page-application

我正在一个页面应用程序网站上工作。所有导航都在div内进行。我使用addEventListener单击来查找链接,防止使用常规href并在div中打开它。

使用此代码,我可以更改页面,保持页眉和页脚而不刷新整个页面。

var spa_array = Array.from(document.getElementsByClassName('spa')); // Array with history (for the back button)

spa_array.forEach( function(b) {
    var id = b.id;
    b.addEventListener('click', function(e) {
        event.preventDefault(); // Prevent href
        history.pushState({id:id}, null, id); // Change url on browser
        openPage(id);
    });
});

window.addEventListener('popstate', function(e) {
    openPage(e.state.id);
});

function openPage(url) {
    var encodedUrl = encodeURI(url);
    $("#spa").load(encodedUrl); // open link inside the div
}

这是发生问题的地方:我使用JS在div上加载新页面,例如index_2.html。 index_2.html页面上的链接不会触发JS addEventListener,因此它将刷新页面并打开新链接。

JS不会应用于.load内部打开的页面。有没有一种方法可以应用相同的脚本,而无需再次调用它(这会造成很多麻烦)?

2 个答案:

答案 0 :(得分:3)

使用委托的事件处理程序:

$("#spa").on('click', '.spa', function(e){
    var anchor = this,
        id = anchor.id;
    e.preventDefault();
    history.pushState({id:id}, null, id);
    openPage(id);
});

您可以在不会被删除的DOM节点上注册处理程序(在您的情况下,其内容会发生变化,但元素本身保持不变),然后将选择器作为第二个参数传入以检查是否单击发生在与选择器匹配的元素内。

这是必要的,因为一旦.load()有更多内容,它将替换之前元素中包含的所有内容,包括您第一次加载时附加的所有事件侦听器。每次更改内容时,您都需要调用循环,但这是一种占用资源少得多的解决方案,可以节省您的麻烦。

答案 1 :(得分:1)

我将提取添加事件侦听器的逻辑,如下所示:

function bindLinks() {
  var spa_array = Array.from(document.getElementsByClassName('spa'));
  spa_array.forEach( function(b) {
    var id = b.id;
    b.addEventListener('click', function(e) {
      event.preventDefault(); // Prevent href
      history.pushState({id:id}, null, id); // Change url on browser
      openPage(id);
    });
  });
}

这样,您就可以在将html加载到div中之后调用bindLinks()。您可以通过将其作为第二个参数传递给.load()来实现。

function openPage(url) {
  var encodedUrl = encodeURI(url);
  $("#spa").load(encodedUrl, bindLinks);
}