【问题标题】:How can I smoothly scroll the page to top in this AngularJS application with virtual page items?如何在这个带有虚拟页面项的 AngularJS 应用程序中平滑地将页面滚动到顶部?
【发布时间】:2019-01-07 17:24:46
【问题描述】:

我正在使用 Bootstrap 4 和 AngularJS v1.6.6 制作一个小型 Contacts 应用程序

应用程序只显示一个 Users JSON。由于 JSON 返回大量用户,应用程序还具有分页功能。

// Create an Angular module named "contactsApp"
var app = angular.module("contactsApp", []);

// Create controller for the "contactsApp" module
app.controller("contactsCtrl", ["$scope", "$http", "$filter", function($scope, $http, $filter) {
  var url = "https://randomuser.me/api/?&results=100&inc=name,location,email,cell,picture";
  $scope.contactList = [];
  $scope.search = "";
  $scope.filterList = function() {
    var oldList = $scope.contactList || [];
    $scope.contactList = $filter('filter')($scope.contacts, $scope.search);
    if (oldList.length != $scope.contactList.length) {
      $scope.pageNum = 1;
      $scope.startAt = 0;
    };
    $scope.itemsCount = $scope.contactList.length;
    $scope.pageMax = Math.ceil($scope.itemsCount / $scope.perPage);
  };

  $http.get(url)
    .then(function(data) {
      // contacts arary
      $scope.contacts = data.data.results;
      $scope.filterList();

      // Paginate
      $scope.pageNum = 1;
      $scope.perPage = 24;
      $scope.startAt = 0;
      $scope.filterList();

      $scope.currentPage = function(index) {
        $scope.pageNum = index + 1;
        $scope.startAt = index * $scope.perPage;
      };

      $scope.prevPage = function() {
        if ($scope.pageNum > 1) {
          $scope.pageNum = $scope.pageNum - 1;
          $scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
        }
      };

      $scope.nextPage = function() {
        if ($scope.pageNum < $scope.pageMax) {
          $scope.pageNum = $scope.pageNum + 1;
          $scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
        }
      };

    });
}]);

$('.pagination li a').on('click', function() {
  $("html, body").animate({
    scrollTop: 0
  }, 500);
  return false;
});
.site-wrapper {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

.container {
  max-width: 1200px;
}

.grid {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
}

.grid [class*='col-'] {
  display: flex;
  flex-direction: column;
  margin-bottom: 25px;
}

.grid .item {
  background: #fff;
  border-radius: 2px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.11);
  flex-grow: 1;
  display: flex;
  flex-direction: column;
}

.grid .text {
  padding: 15px 8px;
}

.grid a {
  text-decoration: none;
  word-wrap: break-word;
}

.grid .card-title {
  margin-bottom: 10px;
  line-height: 1.25;
  font-size: 1.2rem;
}

.grid .read-more {
  padding: 0 8px 8px 8px;
  margin-top: auto;
}

.grid .text-muted {
  margin-bottom: 0;
}

.grid .thumbnail {
  padding: 15px;
}

.grid .thumbnail img {
  display: block;
  margin: 0 auto;
  height: auto;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>


<div data-ng-app="contactsApp">
  <div class="container" data-ng-controller="contactsCtrl">
    <div class="grid" ng-if="contactList.length > 0">
      <div data-ng-repeat="contact in contactList | limitTo : perPage : startAt" class="col-xs-12 col-sm-6 col-lg-4 col-xl-3">
        <div class="item">
          <div class="thumbnail"><img ng-src="{{contact.picture.large}}" class="rounded-circle"></div>
          <div class="text">
            <h2 class="card-title text-center">
              {{contact.name.first }} {{contact.name.last }}
            </h2>
            <ul class="list-unstyled mb-0 text-center">
              <li class="text-muted">Lives in {{contact.location.city}}</li>
              <li><a href="mailto:{{contact.email | lowercase}}">{{contact.email | lowercase}}</a></li>
            </ul>
          </div>
          <div class="read-more">
            <a class="btn btn-block btn-sm btn-primary" href="tel:{{contact.cell}}"><i class="fa fa-lg fa-phone-square" aria-hidden="true"></i><span class="pl-2">Call</span></a>
          </div>
        </div>
      </div>
    </div>
    <p ng-if="contactList.length <= 0" class="text-center">There are no contacts</p>
    <div ng-if="pageMax > 1">
      <ul class="pagination pagination-sm justify-content-center">
        <li class="page-item"><a href="#" class="page-link" ng-click="prevPage()"><i class="fa fa-chevron-left"></i></a></li>
        <li ng-repeat="n in [].constructor(pageMax) track by $index" ng-class="{true: 'active'}[$index == pageNum - 1]">
          <a href="#" class="page-link" ng-click="currentPage($index)">{{$index+1}}</a>
        </li>
        <li><a href="#" class="page-link" ng-click="nextPage()"><i class="fa fa-chevron-right"></i></a></li>
      </ul>
    </div>
  </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

随着分页项目的创建有问题,在控制器内部,用于在单击项目时平滑地将页面滚动到顶部的一小段 jQuery 代码,确实工作。

什么是可行的替代方案?

【问题讨论】:

  • 您应该将您的 jquery 代码放置在 DOM 呈现后执行。在您的代码中,您的分页类元素位于 ng-if 中,当您的 jquery 代码在附加事件时“扫描”时,该元素可能不存在的可能性很高。
  • @MukeshVerma 是的,我知道我应该做什么,但我不知道如何去做。使用$(window).load() 也不起作用。
  • 一个 hacky 方法是,因为你的 ng-if 是由 pageMax 变量控制的,所以每当你设置 $scope.pageMax 时,在一段时间后立即放置你的 jquery 代码。这将确保在设置 pageMax 后刷新 DOM 后,您的元素将可用并且您可以附加事件。如果你可以创建codeopen,那么交流会很容易:)

标签: javascript jquery angularjs


【解决方案1】:

// Create an Angular module named "contactsApp"
var app = angular.module("contactsApp", []);

// Create controller for the "contactsApp" module
app.controller("contactsCtrl", ["$scope", "$http", "$filter", "$timeout", function($scope, $http, $filter, $timeout) {
  var url = "https://randomuser.me/api/?&results=100&inc=name,location,email,cell,picture";
  $scope.contactList = [];
  $scope.search = "";
  $scope.filterList = function() {
    var oldList = $scope.contactList || [];
    $scope.contactList = $filter('filter')($scope.contacts, $scope.search);
    if (oldList.length != $scope.contactList.length) {
      $scope.pageNum = 1;
      $scope.startAt = 0;
    };
    $scope.itemsCount = $scope.contactList.length;
    $scope.pageMax = Math.ceil($scope.itemsCount / $scope.perPage);
  };

  $http.get(url)
    .then(function(data) {
      // contacts arary
      $scope.contacts = data.data.results;
      $scope.filterList();

      // Paginate
      $scope.pageNum = 1;
      $scope.perPage = 24;
      $scope.startAt = 0;
      $scope.filterList();

      $scope.currentPage = function(index) {
        $("html, body").animate({
            scrollTop: 0
        }, 300);
        $timeout( function(){
            $scope.pageNum = index + 1;
            $scope.startAt = index * $scope.perPage;
        },0);
      };

      $scope.prevPage = function() {
        if ($scope.pageNum > 1) {
          $scope.pageNum = $scope.pageNum - 1;
          $scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
        }
      };

      $scope.nextPage = function() {
        if ($scope.pageNum < $scope.pageMax) {
          $scope.pageNum = $scope.pageNum + 1;
          $scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
        }
      };
    });
}]);

$('.pagination li a').on('click', function() {
  $("html, body").animate({
    scrollTop: 0
  }, 500);
  return false;
});
.site-wrapper {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

.container {
  max-width: 1200px;
}

.grid {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
}

.grid [class*='col-'] {
  display: flex;
  flex-direction: column;
  margin-bottom: 25px;
}

.grid .item {
  background: #fff;
  border-radius: 2px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.11);
  flex-grow: 1;
  display: flex;
  flex-direction: column;
}

.grid .text {
  padding: 15px 8px;
}

.grid a {
  text-decoration: none;
  word-wrap: break-word;
}

.grid .card-title {
  margin-bottom: 10px;
  line-height: 1.25;
  font-size: 1.2rem;
}

.grid .read-more {
  padding: 0 8px 8px 8px;
  margin-top: auto;
}

.grid .text-muted {
  margin-bottom: 0;
}

.grid .thumbnail {
  padding: 15px;
}

.grid .thumbnail img {
  display: block;
  margin: 0 auto;
  height: auto;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>

<div data-ng-app="contactsApp">
  <div class="container" data-ng-controller="contactsCtrl">
    <div class="grid" ng-if="contactList.length > 0">
      <div data-ng-repeat="contact in contactList | limitTo : perPage : startAt" class="col-xs-12 col-sm-6 col-lg-4 col-xl-3">
        <div class="item">
          <div class="thumbnail"><img ng-src="{{contact.picture.large}}" class="rounded-circle"></div>
          <div class="text">
            <h2 class="card-title text-center">
              {{contact.name.first }} {{contact.name.last }}
            </h2>
            <ul class="list-unstyled mb-0 text-center">
              <li class="text-muted">Lives in {{contact.location.city}}</li>
              <li><a href="mailto:{{contact.email | lowercase}}">{{contact.email | lowercase}}</a></li>
            </ul>
          </div>
          <div class="read-more">
            <a class="btn btn-block btn-sm btn-primary" href="tel:{{contact.cell}}"><i class="fa fa-lg fa-phone-square" aria-hidden="true"></i><span class="pl-2">Call</span></a>
          </div>
        </div>
      </div>
    </div>
    <p ng-if="contactList.length < 1" class="text-center">There are no contacts</p>
    <div ng-if="pageMax > 1">
      <ul class="pagination pagination-sm justify-content-center">
        <li class="page-item"><a href="#" class="page-link" ng-click="prevPage()"><i class="fa fa-chevron-left"></i></a></li>
        <li ng-repeat="n in [].constructor(pageMax) track by $index" ng-class="{true: 'active'}[$index == pageNum - 1]">
          <a href="#" class="page-link" ng-click="currentPage($index)">{{$index+1}}</a>
        </li>
        <li><a href="#" class="page-link" ng-click="nextPage()"><i class="fa fa-chevron-right"></i></a></li>
      </ul>
    </div>
  </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

【讨论】:

  • 请解释您的代码。您添加了什么以及为什么。谢谢! :)
  • 我注入了 $timeout 并更新了$scope.currentPage 函数。您可以阅读here 的文档以了解 $timeout 功能
猜你喜欢
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2013-08-15
相关资源
最近更新 更多