我有一个使用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&amp; 2在页面加载然后当你向下滚动页面时加载另一个带有漂亮淡入的视图,然后加载它的交互式项目。
答案 0 :(得分:12)
在这种情况下,延迟加载控制器可能没有必要(或有效),但可以这样做。
这里有很多事情需要解决,所以我将分段处理。
<强>标记:强>
<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;
});