1

document.body.scrolltop 値が特定の値以上であることの直接的な結果として、Knockout BindingHandler をトリガーしようとしています。ステートメントに基づいてオブザーバブルを作成しようとしました。まず、これは可能ですか?または、計算の一部としてブール値の結果を更新する必要がありますか?

scrollPosition: KnockoutObservable<boolean> = ko.observable(document.body.scrollTop >= 200)

私も試しました:

scrollPosition: KnockoutComputed<boolean> = ko.computed(() => {
    if (document.body.scrollTop >= 100) {
        return true;
    }
    else {
        return false;
    }
});

関連するコードの残りの部分は次のとおりです。

HTML

<a href="javascript:void(0);" id="topLink" data-bind="topScroll: scrollPosition"><i class="glyphicon glyphicon-stats"></i></a>

CSS

#topLink {
    position: fixed;
    bottom: 40px;
    right: 40px;
    background: rgba(72,72,72,1);
    width: 50px;
    height: 50px;
    display: none;
    text-decoration: none;
    -webkit-border-radius: 35px;
    -moz-border-radius: 35px;
    border-radius: 35px;
    -webkit-transition: all 0.3s linear;
    -moz-transition: all 0.3s ease;
    -ms-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
}

BindingHandler

ko.bindingHandlers.topScroll = {
    update: function (element, valueAccessor) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever any observables/computeds that are accessed change
        // Update the DOM element based on the supplied values here.

        var value = valueAccessor();

        if (ko.unwrap(value)) {

            $(element).css("display", "block");
        }
    }
};

私の目的は、トップスクロールが特定の値を超えると、トップに戻るスタイルのリンクを表示することです。誰かが私が間違っているところを指摘できますか?

4

2 に答える 2

2

...まず、これは可能ですか?または、計算の一部としてブール値の結果を更新する必要がありますか?

scrollPosition = ko.observable(document.body.scrollTop >= 200)

scrollPositionを動的にするつもりです。あなたが実際に望むのはbody.scrollTop、オブザーバブルであることです。しかし、そうではありません。厳密に言えば、いいえ、これは不可能です。

私がお勧めするのは、ユーザーがスクロールしているとき ( this に似ている) を検出し、その結果、監視対象を更新する要素にカスタム バインディング ハンドラーを作成することです。body

ビューでそれを使用する方法の擬似コードを次に示します。

<body data-bind="changeOnScroll: shouldShowLink">

カスタム バインディング ハンドラーは次のようになります (疑似コード)。

ko.bindingHandlers.changeOnScroll = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here

        element.onscroll = function() {
            var obs = valueAccessor();
            obs(element.scrollTop > 200); // set the observable
        }
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever any observables/computeds that are accessed change
        // Update the DOM element based on the supplied values here.

        // Nothing here, since it's a one-way binding from DOM to observable.
    }
};

私は を使用onscrollしましたが、正規化されたイベント処理に使用できる場合は jQuery を使用することもできます。

于 2016-05-10T11:25:06.683 に答える
1

ここでJeroenからの回答を見る前に、私は満足している解決策を見つけました。BindingHandler データ バインドに固定の true を渡しました。

<a href="javascript:void(0);" id="topLink" data-bind="topScroll: true"><i class="glyphicon glyphicon-stats"></i></a>

そして、BindingHandler を次のように修正しました...

ko.bindingHandlers.topScroll = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        $(window).scroll(function() {

            if ($(this).scrollTop() >= 150) {         // If page is scrolled more than 150px

                $(element).css("display", "block");  // show the arrow
            } else {
                $(element).css("display", "none");   // don't show the arrow
            }
        });

        $(element).click(function () {      // When arrow is clicked
            $('body,html').animate({
                scrollTop: 0                       // Scroll to top of body
            }, 'slow');
        });

    }    
};  
于 2016-05-10T12:44:56.943 に答える