【问题标题】:Using md-virtual-repeat inside md-select not working?在 md-select 中使用 md-virtual-repeat 不起作用?
【发布时间】:2018-05-09 06:34:14
【问题描述】:

我想使用 md-select 向用户显示大量数据。打开 md-select 时,浏览器冻结。因此,作为一种解决方案,我想在 md-select 中使用 md-virtual repeat 以获得更好的性能。但是代码(不只是为我工作。我在这里做错了吗?

<md-input-container flex>
  <label>test</label>
  <md-select ng-model="$ctrl.haha">
    <md-virtual-repeat-container id="vertical-container">
      <md-option md-virtual-repeat="item in ctrl.infiniteItems" md-on-demand ng-value="item" ng-selected="$first">
        {{item}}
      </md-option>
    </md-virtual-repeat-container>
  </md-select>
</md-input-container>

#vertical-container {
  height: 256px;
}

this.infiniteItems = {
  numLoaded_: 0,
  toLoad_: 0,
  items: [],

  // Required.
  getItemAtIndex(index) {
    if (index > this.numLoaded_) {
      this.fetchMoreItems_(index);
      return null;
    }
    return this.items[index];
  },

  // Required.
  getLength() {
    return this.numLoaded_ + 5;
  },

  fetchMoreItems_(index) {
    if (this.toLoad_ < index) {
      this.toLoad_ += 20;
      for (let i = 0; i < 10000; i++) {
        this.items.push(i);
      }
      this.numLoaded_ = this.toLoad_;
    }
  }
};

【问题讨论】:

    标签: javascript typescript material-design angular-material


    【解决方案1】:

    为了使这种组合起作用,您需要确保您的 virtual-repeat-container 保持同步。如果您编写一个在打开选择时调用的简单“刷新”函数:

    function () {
        return $timeout(function () {
            $scope.$broadcast("$md-resize");
        }, 100);
    };
    

    应该够了。工作示例:

    angular.module("app", ["ngMaterial", "ngSanitize", "ngAnimate"])
      .controller("MainController", function($scope, $timeout) {
    
        // refresh virtual container
        $scope.refresh = function() {
          return $timeout(function() {
            $scope.$broadcast("$md-resize");
          }, 100);
        };
    
        $scope.infiniteItems = {
          _pageSize: 10000,
          toLoad_: 0,
          items: [],
    
          getItemAtIndex(index) {
            if (index > this.items.length) {
              this.fetchMoreItems_(index);
              return null;
            }
            return this.items[index];
          },
    
          getLength() {
            return this.items.length + 5;
          },
    
          fetchMoreItems_(index) {
            if (this.toLoad_ < index) {
              this.toLoad_ += this._pageSize;
    
              // simulate $http request
              $timeout(angular.noop, 300)
                .then(() => {
                  for (let i = 0; i < this._pageSize; i++) {
                    this.items.push(i)
                  }
                });
            }
          }
        };
    
      });
    #vertical-container {
      height: 256px;  
    }
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>select with md-virtual-repeat</title>
        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.9/angular-material.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-aria.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-animate.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-sanitize.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.9/angular-material.min.js"></script>
      </head>
      <body>
        <div class="main" ng-app="app" ng-controller="MainController" layout="column" layout-align="center center" layout-fill>
          <md-input-container>
            <label>Select an option</label>
            <md-select ng-model="haha" md-on-open="refresh()">
              <md-virtual-repeat-container id="vertical-container">
                <md-option md-virtual-repeat="item in infiniteItems" md-on-demand="" ng-value="item" ng-selected="haha==item">{{item}}</md-option>
              </md-virtual-repeat-container>
            </md-select>
          </md-input-container>
        </div>
        </script>
      </body>
    
    </html>

    您也可以查看this类似的答案。

    【讨论】:

    • 谢谢!如果我使用 javaScript,它可以工作,但是我在将 Refresh() 函数转换为打字稿函数时遇到了一些问题......关于如何在打字稿中使用 $broadcast 的任何想法?因为只有按 f12 才会显示 select 语句中的元素。我认为这是因为 $broadcast 的实施不好
    • 它应该和这个例子没什么不同,也许你忘了在你的控制器类中注入$scope?很难从您发布的代码中分辨出来.. 也许您应该看看this 答案或相关的,祝您好运!
    • 这就是问题所在。再次感谢!
    • 是否可以将过滤器与 md-virtual-repeat 一起使用?我正在尝试使用它,但收到错误“选择中不允许重复的 md 选项值”。
    【解决方案2】:

    根据https://github.com/angular/material/issues/10868 这个帖子,不同的 angularjs 版本有不同的行为。 return $timeout 函数也应该有window.dispatchEvent(new Event('resize')); 语句。

    最终的 $timeout 函数如下所示。

    return $timeout(function() {
       $scope.$broadcast("$md-resize");
       window.dispatchEvent(new Event('resize'));
    },100);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-26
      • 2016-11-30
      • 2017-02-08
      • 1970-01-01
      • 2017-05-17
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多