2

AngularJS ディレクティブを使用してカスタム スクロール ペイン コンポーネントを実装しようとしています。次のjsfiddleの例では、基本的なプロトタイプの例を示しています。

ここに私の考えのスキーマがあります: ここに画像の説明を入力

ディレクティブ コードは次のとおりです。

    myApp.directive('lpScrollPane', function factory() {
    return {
        restrict: 'A',
        replace: true,
        transclude: true,
        template: '<div class="scrollPaneWrapper"><div class="scrollPane" ng-transclude></div><div class="thumbTrack" ></div></div>',
        compile: function (tElement, tAttrs) {
            var minHeight = 30;
            return function (scope, iElement, iAttrs) {
                var thumbTrack = angular.element(iElement.children()[1]);

                scope.onScrollHeight = function () {
                    console.log(iElement.children()[0].scrollHeight);

                    var H1 = iElement[0].offsetHeight;
                    var H2 = iElement.children()[0].scrollHeight;
                    if (H2 > H1) {
                        var trackHeight = Math.round(minHeight + (H1 - minHeight) * (1 - Math.pow((H2 - H1) / H2, 0.8)));
                        thumbTrack.css({
                            display: "block",
                            height: trackHeight + "px"
                        });
                        console.log(H2, H1, trackHeight);
                    } else {
                        thumbTrack.css({
                            display: "none"
                        });
                    }
                };

                scope.$watch(function () {
                    scope.onScrollHeight();
                    //setTimeout(scope.onScrollHeight, 100)
                });


            }
        }
    };
});

基本的に、オーバーフローが非表示の 2 つのダイブと、オーバーフロー スクロールのあるダイブ、サム トラッカーを模倣する別の div があります。

私の目標は、scrollHeight プロパティを監視し、それに応じてトラッカーの高さを変更することです。問題は、DOM がレンダリングされる前に $watch が起動されるため、トラッカーの表示と計算に遅延が生じることです。今のところ、watch 関数で setTimeout を使用しましたが、正常に動作します (35 行目のコメントを外し、34 行目のコメントを外して動作を確認してください)。

それを行う正しい方法は何ですか?

4

2 に答える 2

5

Angular JS ディレクティブのポスト レンダリング コールバックがあることを確認してください。

残念ながら、レンダリングがいつ完了したかを判断する方法はありません (たとえば、イベントがない場合)。$timeout を使用することが、利用可能な最善の回避策のようです。

$('tr').length > 3上記のリンクで、@Nik は、レンダリングがいつ完了したかを判断するために、彼の特定のシナリオをチェックしているとコメントで述べました。レンダリングが完了したことを確認するために、DOM で定期的に調べることができるものがあるかもしれません。

于 2013-01-09T17:37:22.710 に答える
4

2つの観察:

  • compile私見は必要ありませんが、link機能します
  • タイムアウトを使用する代わりに、要素の準備ができるまで待つ必要があります

それで:

myApp.directive('lpScrollPane', function factory() {
  return {
    restrict: 'A',
    replace: true,
    transclude: true,
    template: '<div class="scrollPaneWrapper"><div class="scrollPane" ng-transclude></div><div class="thumbTrack" ></div></div>',
    link: function (scope, iElement, iAttrs) {
      var minHeight = 30;
      var thumbTrack = angular.element(iElement.children()[1]);

      scope.onScrollHeight = function () {
        console.log(iElement.children()[0].scrollHeight);

        var H1 = iElement[0].offsetHeight;
        var H2 = iElement.children()[0].scrollHeight;
        if (H2 > H1) {
          var trackHeight = Math.round(minHeight + (H1 - minHeight) * (1 - Math.pow((H2 - H1) / H2, 0.8)));
          thumbTrack.css({
            display: "block",
            height: trackHeight + "px"
          });
          console.log(H2, H1, trackHeight);
        } else {
          thumbTrack.css({
            display: "none"
          });
        }
      };

      iElement.ready(function () {  
         scope.$watch(function () {
           scope.onScrollHeight();
         });
      });        
    }
  };
});

jsFiddleを参照してください。

編集:

2つの画像が1000語を超えると言っているので、ここに2つのスクリーンショットがあります。 まだ表示可能な最後の要素が挿入されます 表示できない最初の要素が挿入されます

于 2013-01-09T13:20:59.107 に答える