简体   繁体   English

滚动更改导航活动类

[英]Change navigation active class on scroll

I'm trying to make a navigation bar that's similar in functionality to this: https://jsfiddle.net/05jpxf45/ but using Knockout. 我正在尝试制作一个功能类似于此的导航栏: https : //jsfiddle.net/05jpxf45/,但使用的是Knockout。

This is the relevant code from my View Model: 这是我的视图模型中的相关代码:

    self.selectedTopicName = ko.observable("");

    self.selectedTopicName.subscribe(function () {
        self.updateHighlight();
    });

    self.updateHighlight = function () {
        $('.navigation-list li').each(function (index) {
           var navTopic = $(this).attr('class').split(/\s+/)[0];
            $(this).removeClass('highlight');

            if (self.selectedTopicName().indexOf(navTopic) >= 0) {
                $(this).addClass('highlight');
            }
        });
    };

    self.scrollToPage = function (sectionRef) {
        var target = $(sectionRef);
        if (target.length) {
            console.log(target.position().top);
            $('html, body').stop().animate({
                scrollTop: target.position().top
            }, 1000);
        }

(self.selectedTopicName is set in my View whenever the user scrolls, so that bit is sorted). (每当用户滚动时,都会在我的视图中设置self.selectedTopicName,以便对该位进行排序)。

<nav class="floating-nav-container">
<ul data-bind="foreach: sideMenuPageUnitData, attr: { class: 'navigation-list' }">
    <li data-bind="attr: { class: pageRef }">
        <a data-bind="attr: { href: pageData[0].name }, text: name, click: function (data, event) { $parent.scrollToPage('#section_' + pageData[0].name) }"></a>
    </li>
</ul>
<span data-bind="text: selectedTopicName()"></span>
</nav>

(This is working as I want it, I'm just putting it here to show my outline.) (这是我想要的,我只是将其放在此处以显示我的轮廓。)

While this way works, it doesn't seem like it's the "best" way to do it in Knockout and I was wondering if anyone would mind giving me some advice on how they'd do it. 尽管这种方法可行,但似乎并不是在淘汰赛中“最佳”的方法,我想知道是否有人会介意给我一些有关如何做的建议。

Basically everytime selectedTopicName updates, that means the user has scrolled up or down the page, so at the moment I use a subscribe and then loop through the elements but it doesn't seem very elegant. 基本上,每次selectedTopicName更新时,这意味着用户已经向上或向下滚动了页面,因此,此刻我使用订阅,然后遍历元素,但这看起来并不优雅。

Thanks! 谢谢!

When using Knockout to do custom behavior with the DOM that isn't easily done using the built-in bindings, you should create custom bindings. 当使用Knockout对使用内置绑定不容易完成的DOM进行自定义行为时,应创建自定义绑定。 I've taken your code and turned it into a custom binding (for the scroll part, anyway): 我已将您的代码转换为自定义绑定(无论如何,对于滚动部分):

ko.bindingHandlers.onScroll = {
  init: function(element) {
    $(document).on("scroll", function() {
      var scrollPos = $(document).scrollTop();
      $(element).find('a').each(function() {
        var currLink = $(this);
        var refElement = $(currLink.attr("href"));
        if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
          $(element).find('a').removeClass("active");
          currLink.addClass("active");
        } else {
          currLink.removeClass("active");
        }
      });
    });
  }
};

https://jsfiddle.net/05jpxf45/1/ https://jsfiddle.net/05jpxf45/1/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM