Angular JS: 컨트롤러 및 콘텐츠 로드 지연
이 간단한 시나리오에서는 index.htm과 lazy.htm의 2개의 파일이 있습니다.
index.htm:
var myApp = angular.module('myApp', []);
myApp.controller('embed',function($scope){
$scope.embed = 'Embedded Controller';
});
<div ng-controller="embed">{{embed}}</div>
<div ng-include="'lazy.htm'"></div>
게으름뱅이.htm
myApp.controller('lazy',function($scope){
$scope.lazy = 'Lazy Controller';
});
<div ng-controller="lazy">
{{lazy}}
</div>
결과는 오류입니다. "인수 'lazy'는 함수가 아닙니다. 정의되지 않았습니다."
대신 기능 사용
게으름뱅이.htm
function lazy($scope) {
$scope.lazy = 'Lazy Controller';
}
<div ng-controller="lazy">
{{lazy}}
</div>
이 기능은 버전 1.3 베타 14까지 작동합니다.베타 15에서는 글로벌 컨트롤러 기능(https://github.com/angular/angular.js/issues/8296이 삭제되었습니다.
그럼 lazy.htm의 각진 콘텐츠를 동적으로 얻는 더 좋은 방법은 무엇일까요?
갱신:
이 기사(http://ify.io/lazy-loading-in-angularjs))에서 저는 다른 가능한 해결책을 찾았습니다.$controllerProvider를 사용하면 각도 부트스트랩 후에 새로운 컨트롤러를 등록할 수 있습니다.마법처럼 작동한다.v1.3.0-beta에서 테스트 완료.열여덟 살
index.htm:
var myApp = angular.module('myApp', [])
.controller('embed',function($scope){
$scope.embed = 'Embedded Controller';
})
.config(function($controllerProvider) {
myApp.cp = $controllerProvider;
});
<div ng-controller="embed">{{embed}}</div>
<div ng-include="'lazy.htm'"></div>
게으름뱅이.htm
myApp.cp.register('lazy',function($scope){
$scope.lazy = 'Lazy Controller';
});
<div ng-controller="lazy">
{{lazy}}
</div>
업데이트 2:
그 밖에 효과가 있는 2가지 대안은 다음과 같습니다.
게으름뱅이.htm
_app = $('[ng-app]').scope();
_app.lazy = function($scope) {
$scope.lazy = 'Lazy Controller';
};
또는
var $rootScope = $('[ng-app]').injector().get('$rootScope');
$rootScope.lazy = function($scope) {
$scope.lazy = 'Lazy Controller';
};
하지만 저는 이 마지막 두 가지 예가 생산에 사용되어서는 안 된다고 생각합니다.
jquery를 $routeProvider 해결과 함께 사용할 수도 있습니다.
app.module
/* Module Creation */
var app = angular.module ('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function($routeProvider, $controllerProvider){
/*Creating a more synthesized form of service of $ controllerProvider.register*/
app.registerCtrl = $controllerProvider.register;
function loadScript(path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else
result.resolve();
}
};
script.onerror = function () { result.reject(); };
document.querySelector("head").appendChild(script);
return result.promise();
}
function loader(arrayName){
return {
load: function($q){
var deferred = $q.defer(),
map = arrayName.map(function(name) {
return loadScript('js/controllers/'+name+".js");
});
$q.all(map).then(function(r){
deferred.resolve();
});
return deferred.promise;
}
};
}
$routeProvider
.when('/', {
templateUrl: 'views/foo.html',
resolve: loader(['foo'])
})
.when('/bar',{
templateUrl: 'views/bar.html',
controller: 'BarCtrl',
resolve: loader(['bar'])
})
.otherwise({
redirectTo: document.location.pathname
});
}]);
/syslog/foo.displays
<section ng-controller='FooCtrl'>
{{text}}
</section>
js/controllers/foo.disples
/*Here we use the synthesized version of $controllerProvider.register
to register the controller in view*/
app.registerCtrl('FooCtrl',function($scope){
$scope.text = 'Test';
});
/syslog/bar.syslog
<section>
{{text2}}
</section>
js/controllers/bar.disples
app.registerCtrl('BarCtrl',function($scope){
$scope.text2 = 'Test';
});
///JConfig 파일---------
window.angularApp.config(function ($routeProvider,$controllerProvider,$compileProvider,$provide, azMessages) {
$routeProvider.when('/login', {
resolve: {
load: ['$q', '$rootScope', function ($q, $rootScope) {
var deferred = $q.defer();
require([
//load required Js file here
], function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
} ]
}
});
$routeProvider.otherwise({ redirectTo: '/login' });
window.angularApp.components = {
controller: $controllerProvider.register,
service: $provide.service,
directive: $compileProvider.directive
}
//컨트롤러 선언
angularApp.components.controller('DiscussionController',[function(){
}]);
처음에 나는 André Betiolo의 대답을 이용했다.단, Ajax 로딩이 논블로킹이기 때문에 스크립트가 로드되기 전에 뷰가 컨트롤러를 요구할 수 있기 때문에 항상 동작하는 것은 아닙니다.
해결책으로 모든 스크립트가 정상적으로 로드될 때까지 함수가 돌아가지 않도록 했습니다.이것은 다소 해킹적이지만 해결을 완료하기 전에 로드가 성공했는지 확인합니다.또, 복수의 컨트롤러를 로드할 수도 있습니다.
app.module
var app = angular.module ('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function($routeProvider, $controllerProvider){
/*Creating a more synthesized form of service of $ controllerProvider.register*/
app.registerCtrl = $controllerProvider.register;
//jquery to dynamically include controllers as needed
function controllers(controllers){
var numLoaded = 0;
for (i = 0; i < controllers.length; i++) {
$.ajaxSetup({async:false});
$.getScript('js/controllers/' + controllers[i] + '.js').success(function(){
numLoaded++;
if (numLoaded == controllers.length) {
return true; //only return after all scripts are loaded, this is blocking, and will fail if all scripts aren't loaded.
}
});
}
}
$routeProvider
.when('/', {
templateUrl: 'views/foo.html',
resolve: {
load: function () {
controllers(['foo'])
}
}
})
.when('/bar',{
templateUrl: 'views/bar.html',
controller: 'BarCtrl',
resolve: {
load: function () {
controllers(['bar','foo']) //you can load multiple controller files
}
}
})
.otherwise({
redirectTo: document.location.pathname
});
}]);
/syslog/foo.displays
<section ng-controller='FooCtrl'>
{{text}}
</section>
/syslog/bar.syslog
<section ng-controller='BarCtrl'>
{{text2}}
</section>
<section ng-controller='FooCtrl'>
{{text}}
</section>
/controllers/bar.disples
app.registerCtrl('BarCtrl',function($scope){
$scope.text2 = 'Test';
});
순수한 Angular를 가질 수 있습니다.JS의 부하가 느리다.
"Lazy Service" 작성:
var ng = angular.module('app');
ng.factory('lazyService', [ '$http', function($http) {
var jsPath = 'js/${ name }.js';
var promisesCache = {};
return {
loadScript: function(name) {
var path = jsPath.replace('${ name }', name);
var promise = promisesCache[name];
if (!promise) {
promise = $http.get(path);
promisesCache[name] = promise;
return promise.then(function(result) {
eval(result.data);
console.info('Loaded: ' + path);
});
}
return promise;
}
}
}]);
다음으로 설정을 정의합니다.
var ng = angular.module('app', [ 'ngRoute' ]);
ng.config([ '$routeProvider', '$controllerProvider', '$provide', function($routeProvider, $controllerProvider, $provide) {
// Lazy loading
ng.lazy = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
}
$routeProvider
.when('/', {
templateUrl: 'view/home.html'
})
.when('/vendor', {
templateUrl: 'view/vendor.html',
resolve: {
svc: [ 'lazyService', function(lazyService) {
return lazyService.loadScript('services/vendor');
}],
ctrl: [ 'lazyService', function(lazyService) {
return lazyService.loadScript('controllers/vendor');
}]
}
});
. . .
"js/services/vendor.js"에서 다음과 같이 서비스를 만듭니다.
var ng = angular.module('app');
ng.lazy.service('vendorService', [ function() {
. . .
"js/controllers/vendor.js"에서 다음과 같이 컨트롤러를 만듭니다.
var ng = angular.module('app');
ng.lazy.controller('vendorController', [ function() {
. . .
의 "resolve" 속성은 루트 로드 전에 해결해야 할 약속을 정의합니다.
가장 좋은 방법은 명령어를 사용하여 컨트롤러와 템플릿을 적절한 타이밍에 결합하는 것입니다.현재 바인딩은 발생하지 않습니다.lazy.htm
두 번째 예시와 같이 글로벌 함수를 선언하지 않는 한 적절한 타이밍에 실행할 수 있습니다.
이상적 - 각도에서는 HTML과 JS를 분리하도록 강제합니다.새로운 버전에서는 이것이 더 자주 적용될 수 있습니다.
require를 사용해야 할 수 있습니다.JS http://solutionoptimist.com/2013/09/30/requirejs-angularjs-dependency-injection/
속임수를 써서라도 해 볼래?
ng-controller-controller="'lazy'"
또는
HTML에서
ng-controller-controller="myObject.controller"
어디선가 주입하다
$scope.myObject.controller = $controller('lazy', {$scope: $scope})
이 ARI 플러그인을 Angular JS에 사용해 보십시오.이 기능을 사용하면 컨트롤러 스크립트를 필요에 따라 느리게 로드할 수 있습니다.
Directive를 사용하여 컨트롤러를 로드할 수도 있습니다.
예를 들어 다음과 같습니다.
https://gist.github.com/raphaelluchini/53d08ed1331e47aa6a87
샘플 코드를 보내드립니다.저는 잘 되고 있어요.확인 부탁드립니다.
var myapp = angular.module('myapp', ['ngRoute']);
/* Module Creation */
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function ($routeProvider, $controllerProvider) {
app.register = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
//factory: $provide.factory,
//service: $provide.service
};
// so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
// Here I cannot get the controller function directly so I
// need to loop through the module's _invokeQueue to get it
var queue = angular.module(moduleName)._invokeQueue;
for (var i = 0; i < queue.length; i++) {
var call = queue[i];
if (call[0] == "$controllerProvider" &&
call[1] == "register" &&
call[2][0] == controllerName) {
app.register.controller(controllerName, call[2][1]);
}
}
}
var tt = {
loadScript:
function (path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else {
result.resolve();
}
}
};
script.onerror = function () { result.reject(); };
document.querySelector(".shubham").appendChild(script);
return result.promise();
}
}
function stripScripts(s) {
var div = document.querySelector(".shubham");
div.innerHTML = s;
var scripts = div.getElementsByTagName('script');
var i = scripts.length;
while (i--) {
scripts[i].parentNode.removeChild(scripts[i]);
}
return div.innerHTML;
}
function loader(arrayName) {
return {
load: function ($q) {
stripScripts(''); // This Function Remove javascript from Local
var deferred = $q.defer(),
map = arrayName.map(function (obj) {
return tt.loadScript(obj.path)
.then(function () {
registerController(obj.module, obj.controller);
})
});
$q.all(map).then(function (r) {
deferred.resolve();
});
return deferred.promise;
}
};
};
$routeProvider
.when('/first', {
templateUrl: '/Views/foo.html',
resolve: loader([{ controller: 'FirstController', path: '/MyScripts/FirstController.js', module: 'app' },
{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' }])
})
.when('/second', {
templateUrl: '/Views/bar.html',
resolve: loader([{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' },
{ controller: 'A', path: '/MyScripts/anotherModuleController.js', module: 'myapp' }])
})
.otherwise({
redirectTo: document.location.pathname
});
}])
HTML 페이지:
<body ng-app="app">
<div class="container example">
<!--ng-controller="testController"-->
<h3>Hello</h3>
<table>
<tr>
<td><a href="#/first">First Page </a></td>
<td><a href="#/second">Second Page</a></td>
</tr>
</table>
<div id="ng-view" class="wrapper_inside" ng-view>
</div>
<div class="shubham">
</div>
</div>
고마워
언급URL : https://stackoverflow.com/questions/25168593/angularjs-lazy-loading-controllers-and-content
'programing' 카테고리의 다른 글
Oracle에서 톱1을 달성하려면 어떻게 해야 합니까? (0) | 2023.03.10 |
---|---|
Oracle 포트를 포트 8080에서 변경 (0) | 2023.03.10 |
Swagger TypeError: '창'에서 'fetch'를 실행하지 못했습니다. GET/HEAD 메서드를 사용하는 요청에는 본문을 사용할 수 없습니다. (0) | 2023.03.10 |
포스트백 후 javascript 기능 실행 (0) | 2023.03.10 |
Woocommerce 3+의 [내 계정 주문(My Account Orders)]테이블에 커스텀 컬럼 추가 (0) | 2023.03.05 |