当前位置: 首页 > 面试题库 >

在页面滚动上延迟加载Angular视图和控制器

南门魁
2023-03-14
问题内容

我有一个利用Laravel和Angular的微型网站。这是一个具有响应能力的一页微型网站,分为5个部分。我想延迟加载它们以减少一次加载。

<body ng-app>

 <div id="wrapper">
  <section id="intro">1</section>
  <section id="Second">2</section>
  <section id="Third">3</section>
  <section id="Fourth">4</section>
  <section id="Fifth">5</section>
 </div>

</body>

我希望在页面加载时加载1和2,然后在您向下滚动页面时加载带有很好的淡入度的另一个视图,然后加载其交互项。


问题答案:

在这种情况下,可能没有必要(或没有效率)延迟加载控制器,但是可以做到这一点。

这里有很多事情要解决,所以我将分节处理。

现场演示在这里(单击)。

标记:

<div class="container">
  <section
    ng-repeat="section in loadedSections"
    ng-include="section+'.html'"
    scroll-load
    scroll-load-from="sections"
    scroll-load-to="loadedSections"
    ng-animate="{enter:'section-animate-enter'}"
  ></section>
</div>

动画CSS:

.section-animate-enter {
  -webkit-transition: 1.5s linear all;
    transition: 1.5s linear all;
    opacity: 0;
    left: 100%;
}
.section-animate-enter.section-animate-enter-active {
    opacity: 1;
    left: 0;
}

角度逻辑:

app.controller('myCtrl', function($scope) {
  $scope.sections = ['top','mid','bottom']; //html files to load (top.html, etc)
  $scope.loadedSections = [$scope.sections[0]]; //loaded html files
});

app.directive('scrollLoad', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var to = scope[attrs.scrollLoadTo]; //$scope.loadedSections
      var from = scope[attrs.scrollLoadFrom]; //$scope.sections

      $window = angular.element(window);
      $window.bind('scroll', function(event) {
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0;
        var scrollPos = scrollTop + document.documentElement.clientHeight;
        var elemBottom = element[0].offsetTop + element.height();
        if (scrollPos >= elemBottom) { //scrolled to bottom of scrollLoad element
          $window.unbind(event); //this listener is no longer needed.
          if (to.length < from.length) { //if there are still elements to load
            //use $apply because we're in the window event context
            scope.$apply(to.push(from[to.length])); //add next section
          }
        }
      });
    }
  };
});

延迟加载的控制器和滚动视图(动画)。

现场演示在这里(单击)。

标记:

<div class="container">
  <!-- the "lazy" directive will get the controller first, then add ng-include -->
  <section
    ng-repeat="section in loadedSections"
    lazy="section"
    scroll-load
    scroll-load-from="sections"
    scroll-load-to="loadedSections"
    ng-animate="{enter:'section-animate-enter'}"
  ></section>
</div>

角度逻辑:

var $appControllerProvider; //see below

var app = angular.module('myApp', []);

app.config(function($controllerProvider) {
  $appControllerProvider = $controllerProvider; //cache this so that we can lazy load controllers
});

app.controller('myCtrl', function($scope) {
  $scope.sections = ['top','mid','bottom']; //html files to load (top.html, etc)
  $scope.loadedSections = [$scope.sections[0]]; //loaded html files
});

app.directive('scrollLoad', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var to = scope[attrs.scrollLoadTo]; //$scope.loadedSections
      var from = scope[attrs.scrollLoadFrom]; //$scope.sections

      $window = angular.element(window);
      $window.bind('scroll', function(event) {
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0;
        var scrollPos = scrollTop + document.documentElement.clientHeight;
        var elemBottom = element[0].offsetTop + element.height();
        if (scrollPos >= elemBottom) { //scrolled to bottom of scrollLoad element
          $window.unbind(event); //this listener is no longer needed.
          if (to.length < from.length) { //if there are still elements to load
            //use $apply because we're in the window event context
            scope.$apply(to.push(from[to.length])); //add next section
          }
        }
      });
    }
  };
});

app.factory('myService', function($http, $q) {
  return {
    getController: function(fileName) {
      return $http.get(fileName+'.js').then(function(response) {
        return response.data;
      });
    }
  }
});

app.directive('lazy', function(myService, $compile, $q) {
  /* I store the directive in a variable then return it later
   * so that I can abstract directive logic into other functions below */
  var directiveReturn = {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var loadName = scope.$eval(attrs.lazy);

      //this is straightforward - see the "addScript" function for explanation
      myService.getController(loadName).then(function(js) {
        return addScript(loadName, js, scope);
      }).then(function() {
        //the controller has been lazy loaded into angular
        //now use "ng-include" to lazy load the view.
        var ngInc = angular.element('<span></span>')
          .attr('ng-include', "'"+loadName+".html'")
          .attr('ng-controller', loadName+'Ctrl');
          element.append(ngInc);
          $compile(ngInc)(scope);
      });
    } //link
  }; //directive return

  /*
   * This is the magic.
   */
  var scriptPromises = {};
  function addScript(loadName, js, scope) {
    if (!scriptPromises[loadName]) { //if this controller hasn't already been loaded
      var deferred = $q.defer();
      //cache promise (which caches the controller when resolved)
      scriptPromises[loadName] = deferred.promise;

      //inject controller into a script tag
      var script = document.createElement('script');
      script.src = 'data:text/javascript,' + encodeURI(js);
      script.onload = function() {
        //this is how you lazy load a controller
        $appControllerProvider.register(loadName, window[loadName+'Ctrl']);
        //now that the controller is registered with angular, resolve the promise
        //then, it is safe to add markup that uses this controller with ng-controller
        scope.$apply(deferred.resolve());
      };
      //when this script loads, the controller will be registered and promise is resolved
      document.body.appendChild(script);
      return deferred.promise;
    }
    else { //controller already loaded
      return scriptPromises[loadName]; //use cached controller
    }
  }
  return directiveReturn;
});


 类似资料:
  • Flask 通常配合装饰器使用,装饰器使用非常简单,而且使您可以将 URL 和处理它的函数 放在一起。然而这种方法也有一种不足: 这就意味着您使用装饰器的代码必须在前面导入, 否则 Flask 将无法找到您的函数。 这对于需要很快导入的应用程序来说是一个问题,这种情况可能出现在类似谷歌的 App Engine 这样的系统上。所以如果您突然发现您的引用超出了这种方法可以处理 的能力,您可以降级到中央

  • 问题内容: 在这种简化的情况下,我有两个文件:index.htm,lazy.htm。 index.htm: 懒汉 结果是一个错误:“参数’lazy’不是一个函数,未定义” 改用函数 懒汉 直到1.3版本beta 14才可以使用。在beta 15中,删除了全局控制器功能:https : //github.com/angular/angular.js/issues/8296 因此,现在,有什么更好的方

  • 我们的网站通过Netscaler运行,我们已经激活了图像的延迟加载。我试图了解它的功能,以及它是否可以以任何方式控制。例如,如果可以将特定图像设置为非延迟加载。但是我找不到关于它的具体实现的任何东西,只找到描述如何激活它的文章。 如果我理解正确,它就像经典的基于js的lazyloading一样,通过添加类lazy并将src移动到数据原始属性来转换imagetags。然后,当滚动到视图中时,java

  • 问题内容: 我有一个div“框”,当用户滚动到下一页时,它会逐渐使用“ .fp-viewing”作为锚点淡入淡出以开始过渡效果。问题是,当触发.fp- viewing时,页面开始滚动,并且在动画结束之前将框滚动出视图。 触发.fp-viewing时,如何延迟滚动开始,直到box在4s内完成动画播放? 问题答案: 您可以使用fullpage.js提供的选项来取消运动。

  • 问题内容: 我在许多“现代”网站(例如,facebook和google图片搜索)中都注意到了这一点,只有当用户向下滚动页面足以将其带入可见视口区域时,折叠下方的图像才会加载(在查看源时,页面显示_X_个标记,但不是立即从服务器获取的)。这种技术叫什么,它如何工作以及在多少浏览器中工作。并且有一个jQuery插件可以用最少的编码实现此行为。 编辑 奖励:有人可以解释HTML元素是否存在“ onScr

  • 我正在将Recyclerview与CardView一起使用我知道如何在列表视图上控制速度。但对于RecyclerView不是。 更新: 我用这个总结了吉尔的回答