Javascript,SetInterval和SetTimeOut函数导致跳转滚动

时间:2016-10-19 18:36:38

标签: javascript jquery settimeout setinterval squarespace

我正在使用带有特定模板的Squarespace网站,该模板使用索引页面和子页面作为索引页面的内容。 (这些页面可以一个接一个地滚动)。我想Squarespace正在使用锚点从索引页面滚动到相关页面。

我添加了一个javascript来显示当前时间并每秒更新一次(moment.js和moment-timezone)。 我每秒使用SetInterval(function_name,1000)更新时间;

时间每秒都在正确更新。但是,这会导致我正在更新时间的特定页面在尝试向上或向下滚动时保持聚焦(它每秒都会发生)。因此,如果我尝试从更新时间的特定页面向上或向下滚动,它会每秒自动滚动回到该页面!!。

似乎有一个事件触发每一秒导致这个。我每秒呼叫的实际功能如下:

function showLocalTime() {
    var momentLondon = moment().tz("Europe/London").format('HH:mm:ss z');
    // The location label HTML
    var locationHTML = '<strong>Location</strong><br>';
    // The HTML string for london, England
    var londonHTML = 'London, England';
    $( "p:contains('London, England')" ).html(locationHTML + londonHTML + ' (' + momentLondon + ')');
}

因此,我所做的只是更改特定HTML元素的innerHTML以显示当前时间。

我调用上述函数如下:

<script>
  $(function() {
    document.addEventListener("DOMSubtreeModified", function(){
    return;});
    window.setInterval(showLocalTime, 1000); // update it periodically
  });
</script>

但是,正如我所说,通过SetInterval重复调用上述函数会导致网页每秒自动滚动到网站的这一部分(联系人页面)!!。

我可以看到每次调用上面的函数时都会触发一个事件DOMSubtreeModified。我为DOMSubtreeModified事件添加了一个自定义侦听器,但我仍然遇到同样的问题。

可能是因为某种重绘事件?无论如何,我似乎找不到问题,我无法解决这个问题。

任何帮助都将不胜感激!!

由于

2 个答案:

答案 0 :(得分:9)

问题

您每隔<strong>删除并添加两个DOM节点(<br>$.html())。此操作会触发上述DOMSubtreeModified事件,请检查以下测试:

go.onclick = function() {
    document.addEventListener('DOMSubtreeModified', function() {
        alert('Modified');
    });
    test.innerHTML = '<strong>Location</strong><br>';
};
<button id=go>Test</button>
<p id=test></p>

解决方案

而不是使用:

设置html和串联字符串
.html(locationHTML + londonHTML + ' (' + momentLondon + ')');

您应该创建一个DOM节点(<span>元素作为示例),使用textContent属性仅更改必要的内容:

go.onclick = function() {
    wrapper.removeChild(go);
    document.addEventListener('DOMSubtreeModified', function() {
        alert('Modified');
    });
    setInterval(function() {
        test.textContent = new Date;
    }, 1000);
};
<p id=wrapper>
    <button id=go>Test</button>
    <span id=test></span>
</p>

在您的情况下,它将是momentLondon值。 (最后的最后一个例子)

性能

由于您的函数每秒都会运行,因此您应该尽可能地保存最大执行时间。

1 。您可以在函数范围之外声明常量变量,如:

var locationHTML = '<strong>Location</strong><br>';
var londonHTML = 'London, England';

function showLocalTime() {
    // locationHTML ...
    // londonHTML   ...
    // ...
}

2 。另外,如果某个函数总能给出相同的预期结果:

 $("p:contains('London, England')")

您只能在函数范围之外运行一次,并将结果存储在变量中:

var $p = $("p:contains('London, England')");

function showLocalTime() {
    // $p ...
    // ...
}

最终结果

考虑到所有这一切,您的代码最终会像这样:

<script>
$(function() {
    // constants
    var locationHTML = '<strong>Location</strong><br>';
    var londonHTML = 'London, England';
    var $p = $("p:contains('London, England')");

    // prepare your DOM outside showLocalTime
    $p.html(locationHTML + londonHTML + ' (<span></span>)');
    var span = $p.find('span')[0];

    // do only necessary things within setInterval
    setInterval(function showLocalTime() {
        span.textContent = moment().tz('Europe/London').format('HH:mm:ss z');
    }, 1000);
});
</script>

希望它有所帮助。

答案 1 :(得分:0)

我会将showLocalTime函数移动到立即调用的匿名函数中,并在setTimeOut调用之前调用它,这样它会在加载时以及1秒后显示时间。

我为你的代码编写了这个小提示,看看我是否可以重现你的自动滚动问题,这段代码不会导致JSFiddle。

这是JSFiddle: https://jsfiddle.net/workingClassHacker/xhrfoznj/10/

以下是代码:

$(function() {
   var londonP = $("p:contains('London, England')");
   var showLocalTime = function() {
       timeDisplay.textContent = moment().tz("Europe/London").format('HH:mm:ss z');
   }
   londonP.html('<strong>Location</strong><br/>London, England (<span></span>)');
   var timeDisplay = londonP.find('span')[0];
   showLocalTime();
   setInterval(showLocalTime, 1000);
});