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

pla*_*res 7 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 + ')');
}
Run Code Online (Sandbox Code Playgroud)

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

我调用上面的函数如下:

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

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

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

可能是因为某种重绘事件?无论如何,我似乎无法找到问题,我无法克服这个问题.

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

谢谢

Was*_*des 9

问题

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

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

而不是设置html和串联字符串:

.html(locationHTML + londonHTML + ' (' + momentLondon + ')');
Run Code Online (Sandbox Code Playgroud)

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

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

在你的情况下,它将是momentLondon价值.(最后的例子)

性能

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

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

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

function showLocalTime() {
    // locationHTML ...
    // londonHTML   ...
    // ...
}
Run Code Online (Sandbox Code Playgroud)

2.另外,如果函数总是给出相同的预期结果:

 $("p:contains('London, England')")
Run Code Online (Sandbox Code Playgroud)

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

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

function showLocalTime() {
    // $p ...
    // ...
}
Run Code Online (Sandbox Code Playgroud)

最后结果

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

<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>
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.