我正在构建一个blazor应用程序,在这个应用程序中,我应该将java脚本代码保持在最少。所以我在我的视差页面中只使用了引导css。我已经用window.onscroll实现了类似滚动间谍的行为,因为到目前为止还不能用c#完成它;但它的性能很差。
在谷歌搜索之后,我最近偶然发现了IntersectionObserver应用编程接口。所以我想让我现有的window.onscroll逻辑与IntersectionObserver应用程序接口一起工作。然而,我无法做到这一点。
这就是我想要做的。在我的视差页面固定顶部导航栏,我想应用active css类到a.nav-items时,用户滚动达到各自的部分,他想查看。
下面是HTML:
<body data-spy="scroll" data-target=".site-nav" data-offset="55">
<header id="page-hero" class="site-header d-flex flex-column align-content-between">
<nav class="site-nav family-sans navbar navbar-expand-md navbar-dark fixed-top">
<div class="container-fluid">
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#myTogglerNav" aria-controls="myTogglerNav"
aria-label="Toggle Navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand text-uppercase" href="#page-hero">
<i class="fas fa-cube mr-2"></i> Layout Components</a>
<div class="collapse navbar-collapse" id="myTogglerNav">
<div class="navbar-nav ml-auto font-weight-regular text-uppercase">
<a class="nav-item nav-link" href="#page-hero">home</a>
<a class="nav-item nav-link" href="#page-multicolumn">columns</a>
<a class="nav-item nav-link" href="#page-media">media</a>
<a class="nav-item nav-link" href="#page-photogrid">grid</a>
<a class="nav-item nav-link" href="#page-carousel">carousel</a>
<a class="nav-item nav-link" href="#page-nested">nested</a>
<a class="nav-item nav-link" href="#page-icons">icons</a>
<a class="nav-item nav-link" href="#page-floater">floater</a>
<a class="nav-item nav-link" href="#page-cards">cards</a>
</div>
</div>
</div>
</nav>
<section class="layout-hero jumbotron jumbotron-fluid d-flex align-items-center mt-5 text-reverse">
<div class="container text-center">
......
......
......
<article id="page-multicolumn" class="page-section vertical-padding">
<header class="page-section-header container">
.....
.....
.....
<article id="page-media" class="page-section vertical-padding">
<header class="page-section-header container text-center">
....我在顶部.nav-item中有与a的href匹配的id的article标签。我只粘贴了几个html的骨架是相同的所有文章的标签。
这是我现有的window.onscroll
var sections = {};
document.querySelectorAll(".page-section,.site-header").forEach(section => sections[section.id] = section.offsetTop);
window.onscroll = function () {
document.querySelector('header nav').classList.toggle('inbody', document.documentElement.scrollTop > 380);
document.querySelector('#page-media .layout-animation').style['visibility'] = 'hidden';
var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
Object.keys(sections).forEach(key => {
if (sections[key] <= scrollPosition + 55) {
document.querySelectorAll('a.nav-item').forEach(a => a.classList.remove('active'));
document.querySelector('a[href="#' + key + '"]').classList.add('active');
if (key === 'page-media') {
document.querySelector('#page-media .layout-animation').classList.add('animated', 'fadeInRight');
}
}
});
};上面的代码可以工作。但是我想使用正确的API。
这是我的IntersectionObserver
if (window.IntersectionObserver) {
let observer = new IntersectionObserver(
(entries, observer) => {
console.log(entries);
entries.forEach(entry => {
/* Here's where we deal with every intersection */
document.querySelectorAll('a.nav-item').forEach(a => a.classList.remove('active'));
if (entry.isIntersecting) {
document.querySelector('header nav').classList.toggle('inbody', entry.target.id !== 'page-hero');
document.querySelector('#page-media .layout-animation').style['visibility'] = 'hidden';
document.querySelector('a[href="#' + entry.target.id + '"]').classList.add('active');
if (entry.target.id === 'page-media') {
document.querySelector('#page-media .layout-animation').classList.add('animated', 'fadeInRight');
}
}
});
}, { root: document.querySelector('.site-nav'), rootMargin: "0px", threshold: 0 });
document.querySelectorAll('.page-section,.site-header').forEach(section => observer.observe(section));
}但是我的交叉口观察器不工作。我试着使用console.log(entry)来看看会发生什么。所有的条目只在页面加载时被记录下来,并且在那之后就不工作了。请在我错的地方提供帮助。
发布于 2020-01-18 11:32:10
这里的代码不能工作的原因是它在错误的时间运行。对document.querySelectorAll('.page-section,.site-header')的调用需要在这些元素被呈现到DOM中之后执行,否则它将不会匹配任何内容。
这是我是如何工作的,我稍微调整了一下函数,如下所示,
function highlightMenu() {
const sections = document.querySelectorAll('.page-section,.site-header');
const config = {
rootMargin: '-55px 0px -85%'
};
let observer = new IntersectionObserver(function
(entries, self) {
entries.forEach(entry => {
if (entry.isIntersecting) {
intersectionHandler(entry);
}
});
}, config);
sections.forEach(section => observer.observe(section));
}
function intersectionHandler(entry) {
const id = entry.target.id;
document.querySelector('header nav').classList.toggle('inbody', id !== 'page-hero');
if (id === 'page-media') {
document.querySelector('#page-media .layout-animation').classList.add('animated', 'fadeInRight');
}
const currentlyActive = document.querySelector('nav a.nav-item.active');
const shouldBeActive = document.querySelector('nav a.nav-item[href="#' + id + '"]');
if (currentlyActive) {
currentlyActive.classList.remove('active');
}
if (shouldBeActive) {
shouldBeActive.classList.add('active');
}
}并使用blazor中的JS互操作从我的组件OnAfterRenderAsync内部调用,
@code{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("highlightMenu");
}
}
}https://stackoverflow.com/questions/59553761
复制相似问题