ScrollIntoView()不起作用-香草JS,为什么?

时间:2019-03-22 07:30:01

标签: javascript

我的想法是拥有一个简单的搜索功能,人们可以在搜索框中键入文本,然后查看html中是否有与文本匹配的内容。如果是这样,匹配的部分(假设它可能在整个HTML页面的后半部分,在您当前的屏幕/视口中看不到)将会跳转/滚动到视图中。如果没有,您将在#feedback标记中收到“找不到匹配项”消息。

HTML看起来像这样:

<input id="search-text">
<p id="feedback"></p>
<p>title1</p>
<p>title2</p>
<p>title3</p>

JS是这样的:

let searchText = ''

const titlesNodes = document.querySelectorAll('p')
const titles = Array.from(titlesNodes)

document.querySelector('#search-text').addEventListener('input', (e) => {
    searchText = e.target.value
    searchFunction()
})

const searchFunction = () => {
        const filteredTitles = titles.filter((title) => title.innerText.toLowerCase().includes(searchText.toLowerCase()) )
        const msg = document.querySelector('#feedback')
        msg.innerHTML = ''
        if (filteredTitles.length > 0){
            filteredTitles[0].scrollIntoView()
        } else {
            msg.textContent = 'No match found' 
        }
}

到目前为止,我能够获得“找不到匹配项”,但是当我键入仅在页面后半部分的内容时,它不会跳转到视图。我在Chromium和Firefox上都进行了测试,并且使用Linux。

我的代码有什么问题?谢谢!

2 个答案:

答案 0 :(得分:2)

这是因为默认情况下,浏览器会在您键入时将<input>元素设置为屏幕。因此,您自己的调用会被浏览器的默认设置覆盖。

虽然不确定避免这种情况的最佳方法是什么...
您可能会尝试在短暂的超时后调用scrollIntoView,因此发生在输入之一之后。如果使用requestAnimationFrame计时功能,它应该在下一次绘制之前发生,因此您不会注意到其中一个输入发生了。

let searchText = '';


const titlesNodes = document.querySelectorAll('p')
const titles = Array.from(titlesNodes)

document.querySelector('#search-text').addEventListener('input', (e) => {
  searchText = e.target.value
  searchFunction()
})

const searchFunction = () => {
  const filteredTitles = titles.filter((title) => title.innerText.toLowerCase().includes(searchText.toLowerCase()))
  const msg = document.querySelector('#feedback')
  msg.innerHTML = ''
  if (filteredTitles.length > 0) {
    requestAnimationFrame(() => { // wait just a bit
      filteredTitles[0].scrollIntoView()
    });
  } else {
    msg.textContent = 'No match found'
  }
}
#feedback { margin-bottom: 125vh }
p { margin-bottom: 50vh }
<input id="search-text">
<p id="feedback"></p>
<p>title1</p>
<p>title2</p>
<p>title3</p>

答案 1 :(得分:0)

尝试更改:

- filteredTitles[0].scrollIntoView()
+ filteredTitles[0].scrollIntoView({alignToTop: true})
  document.querySelector('#search-text').addEventListener('input', (e) => {
      searchText = e.target.value
-     searchFunction()
+     setTimeout(searchFunction, 500)})
})