延迟加载页面滚动时的角度视图和控制器

 dmcm0011 发布于 2023-02-12 16:09

我有一个使用Laravel和Angular的微型网站.这是一个单页微型网站,响应迅速,分为5个部分.我想懒得加载它们以减少一次加载.



 
1
2
3
4
5

我正在寻找在页面加载时加载1和2然后当您向下滚动页面时加载另一个视图并使用漂亮的淡入淡出然后加载其交互式项目.

1 个回答
  • 在这种情况下,可能没有必要(或有效)延迟加载您的控制器,但它可以完成.

    这里有很多事情需要解决,所以我将分段处理.

    滚动(动画)上的延迟加载视图.

    现场演示(点击).

    标记:

    <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
              }
            }
          });
        }
      };
    });
    

    延迟加载CONTROLLERS和滚动视图(动画).

    现场演示(点击).

    标记:

    <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;
    });
    

    2023-02-12 16:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有