Ответ 1
Хорошо, я прокомментировал свой код, чтобы он все объяснил. Если у вас есть дополнительные вопросы, просто дайте мне знать. Это решение проблем, как это описано в ваших комментариях. Живая демонстрация здесь (нажмите).
Разметка:
<!DOCTYPE html>
<html ng-app="myApp" ng-controller="myCtrl">
<head>
</head>
<body>
<button ng-click="load()">Load Foo</button>
<!-- I'm using this to bootstrap the lazy loaded script -->
<section ng-repeat="item in loaded" lazy="item"></section>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<script src="script.js"></script>
</body>
</html>
JavaScript:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
//array of things to load
$scope.lazyThings = [
{directive:'my-foo-directive', file:'foo.js'}
];
$scope.loaded = [];
$scope.load = function() {
var loadIndex = $scope.loaded.length;
if ($scope.lazyThings[loadIndex]) {
$scope.loaded.push($scope.lazyThings[loadIndex]);
}
}
});
app.factory('myService', function($http) {
return {
getJs: function(path) {
return $http.get(path).then(function(response) {
deferred.resolve(response.data);
});
}
}
});
//this adds an attribute to kick off the directive
//for whatever script was lazy loaded
app.directive('lazy', function($compile, $q, myService) {
var directiveReturn = {
restrict: 'A',
scope: {
lazy: '='
},
link: function(scope, element) {
myService.getJs(scope.lazy.file).then(function(data) {
return addScript(scope.lazy.file, data, scope);
}).then(function() {
var $span = angular.element('<span></span>').attr(scope.lazy.directive, '');
$compile($span)(scope);
element.append($span);
});
}
}
var scriptPromises = {};
function addScript(file, js, scope) {
if (!scriptPromises[file]) { //if this controller hasn't already been loaded
var deferred = $q.defer();
//cache promise)
scriptPromises[file] = deferred.promise;
//inject js into a script tag
var script = document.createElement('script');
script.src = 'data:text/javascript,' + encodeURI(js);
script.onload = function() {
//now the script is ready for use, resolve promise to add the script directive element
scope.$apply(deferred.resolve());
};
document.body.appendChild(script);
return deferred.promise;
}
else { //this script has been loaded before
return scriptPromises[loadFile]; //return the resolved promise from cache
}
}
return directiveReturn;
});
app.directive('myFooDirective', function() {
return {
restrict: 'A',
link: function(scope, element) {
//put the logic from your lazy loaded "foo.js" script here
element.text(foo.someFunction());
}
}
});
Пример ленивой загрузки script:
var foo = {
someFunction: function() {
return 'I am data from a lazy loaded js function!';
}
};
Существует множество способов реализовать концепцию, которую я продемонстрировал здесь. Просто подумайте о том, как вы хотели бы использовать его, и напишите некоторые директивы для его выполнения. Angular делает большинство вещей довольно простыми.
Примечание. Ввод тега script не является обязательным, но я предпочитаю это скорее, чем выполнение script напрямую. При использовании тега script вы сможете отслеживать все загруженные файлы с помощью инструментов dev в разделе "Ресурсы" в разделе "Скрипты".