javascript - IntersectionObserver.observe 不是对象,如何使用IntersectionObserver

标签 javascript css sticky intersection-observer object.observe

我正在使用 css position: sticky 创建一个包含粘性列的表格。当它们“卡住”时,我想以不同的方式设置列的样式。我的第一个元素涉及在第二列部分滑过第一列或 .wdtscroll td:nth-child(1) 时设置样式。 这是javascript

const stickyElm = document.querySelector('.wdtscroll td')

const observer = new IntersectionObserver( 
  ([e]) => e.target.classList.toggle('isSticky', e.intersectionRatio < 1),
  {threshold: [1]}
);

observer.observe(stickyElm)

这是 jsfiddle:https://jsfiddle.net/g421kjcx/

虽然它肯定不是完美的,但我通过将其左侧位置设置为 -1px 来实现这一点,因此一旦您开始水平滚动表格,它就会被设置样式。如您所见,这是有效的,但仅适用于顶部单元格。

当我在我的网站上使用此代码时,它不起作用并且我收到一条警告: “TypeError:IntersectionObserver.observe 的参数 1 不是对象。”

当我查找时,似乎 Object.observe 已过时。

我如何在不使用 Object.observe 的情况下使用此 javascript,以及我如何定位第一列中的所有 td。

额外的问题:当第二列或 .wdtscroll td:nth-child(2) 卡住时,我将如何设计它的样式,即使它永远不会滚动到视口(viewport)之外。

谢谢!

最佳答案

Here is the jsfiddle: https://jsfiddle.net/g421kjcx/

这是我对你的 fiddle 的回应:https://jsfiddle.net/5nfb2qdy/4/

我回答了您在这篇文章中提出的一系列问题:

As you can see this is working but only for the top cell. ...how can I "target" all td's in the first column.

1) 观察者的目标是单个元素(在本例中)。这意味着您不能依赖它来为多个元素设置样式。 相反,这样做:

([e]) => {
    let all_td = document.querySelectorAll('.wdtscroll td:first-child')
    all_td.forEach(entry =>
        entry.classList.toggle('isSticky', e.intersectionRatio < 1)
    )
}

When I use this code on my website, it does not work and I get a warning stating: "TypeError: Argument 1 of IntersectionObserver.observe is not an object."

2) 这很可能是因为 JavaScript 在引用的元素出现在页面上之前就已经运行了。如果此代码块在 <head></head> 中页面的一部分,只需稍作修改即可使其正常工作:

window.onload = function(){
    observer.observe(stickyElm)
}

通过将观察者激活包装在 onload 中,它不会在页面完成呈现之前运行。另一种选择是将所有这些 JavaScript 移动到页面末尾,就在您的 </body></html> 之前。

Bonus question: How would I style the second column or .wdtscroll td:nth-child(2) when it is stuck, even though it will never scroll past the viewport.

3) 也许像这样?

([e]) => {
    let all_td = document.querySelectorAll('.wdtscroll td:nth-child(1)')
    let all_2nd_td = document.querySelectorAll('.wdtscroll td:nth-child(2)')
    all_td.forEach(entry =>
        entry.classList.toggle('isSticky', e.intersectionRatio < 1)
    )
    all_2nd_td.forEach(entry =>
        entry.classList.toggle('isSticky', e.intersectionRatio < 1)
    )
}

同时将此添加到 CSS 的末尾:

.wdtscroll tr td:nth-child(2).isSticky {
  background-color: pink;
}

4) 不是对您的任何问题的回应,但我注意到您的 CSS 通常存在一些问题。以下是我更改的内容:

CSS

/* added td to the selectors of the next 2 rules */
.wdtscroll tr:nth-child(even) td { background-color: #f2f2f2; }

.wdtscroll tr:hover td { background-color: #ddd; }


/* added tr to the selector list to override the background color set above */
.wdtscroll tr td.isSticky{
  background-color: salmon;
}

5) 最后,批评用于对元素进行类分配的方法。您可能有充分的理由为每个 td 分配类属性每个 tr .这也可以通过将样式应用于 td:nth-child(1) 的规则将类属性分配给表本身来更简单地实现。和 td:nth-child(2)只有 2 个 CSS 规则。这将消除在 JavaScript 中循环遍历表格的每一行并利用 CSS 的特性来设置批量元素样式的需要。

CSS:

.wdtscroll.isSticky tr td:nth-child(1) {
  background-color: salmon;
}
.wdtscroll.isSticky tr td:nth-child(2) {
  background-color: pink;
}

JavaScript:

// get the sticky element
const stickyElm = document.querySelector('.wdtscroll td')
const tableElm = document.querySelector('.wdtscroll')

const observer = new IntersectionObserver( 
    ([e]) => {
        tableElm.classList.toggle('isSticky', e.intersectionRatio < 1)
    },
  {threshold: [1]}
);

window.onload = function(){
    observer.observe(stickyElm)
}

对于一个漂亮、简洁、整洁的解决方案来说怎么样? :) 最后的 fiddle :https://jsfiddle.net/5nfb2qdy/5/

关于javascript - IntersectionObserver.observe 不是对象,如何使用IntersectionObserver,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58758085/

相关文章:

html - 单击单选按钮更改文本

CSS body Background 居中以与内容对齐

javascript - 内联 JavaScript 似乎是随机加载的,如果有的话

css - 如何在父元素末尾停止粘性元素

javascript - 是否可以在 Meteor 事件映射中使用嵌套选择器?

javascript - 如何在仍使用现有 CSS 的情况下 append Jquery html 代码

javascript - 我们是否应该滥用与 let 相同的变量,因为我们可以吗?

Javascript 删除弹出窗口中的警告符号

css - 获取滚动条以忽略单个背景 div

javascript - 粘性 header - 相对于动态 header 长度的正文位置