Angular일 때 이벤트 전송JS 로드 완료
모든 디렉티브가 컴파일/링크를 완료했을 때 페이지 로드/부트스트랩의 종료를 검출하는 가장 좋은 방법이 무엇인지 궁금했다.
이미 거기 이벤트가 있나요?부트스트랩 기능을 오버로드해야 합니까?
직감: ngCloak 지시가 어떻게 하는지 보는 것은 어떨까요?ngCloak 디렉티브는, 확실히, 로드 후에 컨텐츠를 표시할 수 있습니다.ngCloak을 보면 정확한 답이 나올 거야
1시간 후 편집:네, 음, 제가 ngCloak을 봤는데 정말 짧아요.이는 {{template}}개의 식(즉, 로드된 템플릿)이 평가될 때까지 컴파일 함수가 실행되지 않는다는 것을 의미하며, 따라서 ngCloak 디렉티브의 훌륭한 기능을 제공합니다.
제가 아는 바로는 ngCloak과 같은 단순함으로 디렉티브를 만들고 컴파일 함수로 원하는 대로 하는 것입니다. :) 디렉티브를 앱의 루트 요소에 배치합니다.디렉티브를 myOnload와 같은 것으로 호출하여 my-onload 속성으로 사용할 수 있습니다.컴파일 함수는 템플릿이 컴파일되면 실행됩니다(식 평가 및 하위 템플릿 로드).
편집, 23시간 후:네, 그래서 조사를 좀 해봤고 제 질문도 해봤습니다.제가 한 질문은 이 질문과 간접적으로 관련이 있었지만, 공교롭게도 이 질문을 푸는 답변으로 이어졌습니다.
답은 간단한 디렉티브를 생성하여 디렉티브의 링크 함수에 코드를 넣을 수 있습니다.이 기능은 대부분의 경우 아래에 설명되어 있습니다.요소가 준비/로드되었을 때 실행됩니다.컴파일 및 링크 기능이 실행되는 순서에 대한 Josh의 설명을 바탕으로,
다음과 같은 마크업이 있는 경우:
<div directive1> <div directive2> <!-- ... --> </div> </div>
그 후 각도JS는 디렉티브 함수를 특정 순서로 실행하여 디렉티브를 작성합니다.
directive1: compile directive2: compile directive1: controller directive1: pre-link directive2: controller directive2: pre-link directive2: post-link directive1: post-link
디폴트로는 스트레이트 "링크" 함수는 포스트 링크이므로 외부 디렉티브1의 링크 함수는 내부 디렉티브2의 링크 함수가 실행될 때까지 실행되지 않습니다.그렇기 때문에 포스트 링크에서 DOM 조작만 해도 안전하다고 말합니다.따라서 원래 질문에서는 외부 디렉티브의 링크 함수에서 하위 디렉티브의 내부 html에 액세스하는 데 문제가 없을 것입니다만, 위와 같이 동적으로 삽입된 콘텐츠를 컴파일해야 합니다.
이것으로, 모든 것이 준비/컴파일/링크/로드되었을 때에, 간단하게 코드의 실행 지시를 내릴 수 있습니다.
app.directive('ngElementReady', [function() {
return {
priority: -1000, // a low number so this directive loads after all other directives have loaded.
restrict: "A", // attribute only
link: function($scope, $element, $attributes) {
console.log(" -- Element ready!");
// do what you want here.
}
};
}]);
서 실행할 수 것은 하고 "ngElementReady"를 설정합니다.console.log
로딩되면 기동합니다.
<body data-ng-app="MyApp" data-ng-element-ready="">
...
...
</body>
그렇게 간단해!그냥 간단한 지시문을 만들어서 사용하세요.;)
할 수 할 수 .$scope.$eval($attributes.ngElementReady);
다음 중 하나를 선택합니다.
app.directive('ngElementReady', [function() {
return {
priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
restrict: "A",
link: function($scope, $element, $attributes) {
$scope.$eval($attributes.ngElementReady); // execute the expression in the attribute.
}
};
}]);
다음으로 임의의 요소에 사용할 수 있습니다.
<body data-ng-app="MyApp" data-ng-controller="BodyCtrl" data-ng-element-ready="bodyIsReady()">
...
<div data-ng-element-ready="divIsReady()">...<div>
</body>
bodyIsReady 및 divIsReady 등의 기능이 요소가 속한 범위(컨트롤러)에 정의되어 있는지 확인합니다.
경고:이건 대부분의 경우에 효과가 있을 거라고 말했잖아요.ngRepeat 및 ngIf와 같은 특정 지시어를 사용할 때는 주의하십시오.그들은 그들만의 범위를 만들고, 당신의 지시가 발사되지 않을 수도 있다.예를 들어 새로운 ngElementReady 디렉티브를 ngIf를 가진 요소에 배치하고 ngIf 조건이 false로 평가되면 ngElementReady 디렉티브는 로드되지 않습니다.또는 예를 들어 ngInclude 디렉티브가 있는 요소에 새로운 ngElementReady 디렉티브를 배치한 경우 ngInclude 템플릿이 존재하지 않으면 디렉티브가 로드되지 않습니다.디렉티브를 모두 같은 요소에 배치하는 것이 아니라 반드시 중첩함으로써 이러한 문제를 회피할 수 있습니다.예를 들어, 다음과 같이 합니다.
<div data-ng-element-ready="divIsReady()">
<div data-ng-include="non-existent-template.html"></div>
<div>
이 대신:
<div data-ng-element-ready="divIsReady()" data-ng-include="non-existent-template.html"></div>
ngElementReady 디렉티브는 후자의 예에서 컴파일되지만 링크 함수는 실행되지 않습니다.주의: 디렉티브는 항상 컴파일되지만 위와 같은 특정 시나리오에 따라 링크 기능이 항상 실행되는 것은 아닙니다.
몇 분 후 편집:
이 한 답변을 ,, 리, 리, 제, 제, 제, 제, 제, 제, 제, 제, 제, 신, 제, 제, oh, oh, oh, oh, oh, oh.$emit
★★★★★★★★★★★★★★★★★」$broadcast
"에서 ng-element-ready
:) 예:) 예 :
<div data-ng-element-ready="$emit('someEvent')">
...
<div>
몇 분 후 편집:
@satchmorun의 답변도 동작하지만 첫 번째 로드에 대해서만 동작합니다.여기 링크 함수를 포함한 실행 순서를 설명하는 매우 유용한 SO 질문이 있습니다.app.run
기타 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,app.run
이 경우 링크 기능이 더 나은 특정 요소에는 해당되지 않습니다.
5개월 후 10월 17일 8:11 PST:
이것은 비동기적으로 로드되는 부분에서는 작동하지 않습니다.파셜에 부기를 추가해야 합니다(예를 들어 각 파셜이 콘텐츠 로딩이 완료된 시점을 추적한 후 이벤트를 내보내 상위 스코프가 로드된 파셜 수를 카운트하고 모든 파셜이 로드된 후에 최종적으로 필요한 작업을 수행하는 방법 등).
10월 23일 오후 10시 52분(태평양 표준시):
이미지가 로드될 때 코드를 실행하라는 간단한 지시를 내렸습니다.
/*
* This img directive makes it so that if you put a loaded="" attribute on any
* img element in your app, the expression of that attribute will be evaluated
* after the images has finished loading. Use this to, for example, remove
* loading animations after images have finished loading.
*/
app.directive('img', function() {
return {
restrict: 'E',
link: function($scope, $element, $attributes) {
$element.bind('load', function() {
if ($attributes.loaded) {
$scope.$eval($attributes.loaded);
}
});
}
};
});
10월 24일 오전 12시 48분(태평양 표준시:
의 것을 개선했다.ngElementReady
을 '지시하다'로 했습니다.whenReady
.
/*
* The whenReady directive allows you to execute the content of a when-ready
* attribute after the element is ready (i.e. done loading all sub directives and DOM
* content except for things that load asynchronously like partials and images).
*
* Execute multiple expressions by delimiting them with a semi-colon. If there
* is more than one expression, and the last expression evaluates to true, then
* all expressions prior will be evaluated after all text nodes in the element
* have been interpolated (i.e. {{placeholders}} replaced with actual values).
*
* Caveats: if other directives exists on the same element as this directive
* and destroy the element thus preventing other directives from loading, using
* this directive won't work. The optimal way to use this is to put this
* directive on an outer element.
*/
app.directive('whenReady', ['$interpolate', function($interpolate) {
return {
restrict: 'A',
priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
link: function($scope, $element, $attributes) {
var expressions = $attributes.whenReady.split(';');
var waitForInterpolation = false;
function evalExpressions(expressions) {
expressions.forEach(function(expression) {
$scope.$eval(expression);
});
}
if ($attributes.whenReady.trim().length == 0) { return; }
if (expressions.length > 1) {
if ($scope.$eval(expressions.pop())) {
waitForInterpolation = true;
}
}
if (waitForInterpolation) {
requestAnimationFrame(function checkIfInterpolated() {
if ($element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
requestAnimationFrame(checkIfInterpolated);
}
else {
evalExpressions(expressions);
}
});
}
else {
evalExpressions(expressions);
}
}
}
}]);
이렇게 , 「이렇게」 「이렇게」 「이렇게」 「이렇게」를 기동할 수 .someFunction
되어 있고, 「」가 되어 있는 .{{placeholders}}
★★★★★★★★★★★★★★★★★★:
<div when-ready="someFunction()">
<span ng-repeat="item in items">{{item.property}}</span>
</div>
someFunction
으로 될 것이다item.property
자리 표시자가 교체됩니다.
을 평가하고 보세요.true
{{placeholders}}
뭇매를 맞다
<div when-ready="someFunction(); anotherFunction(); true">
<span ng-repeat="item in items">{{item.property}}</span>
</div>
someFunction
★★★★★★★★★★★★★★★★★」anotherFunction
{{placeholders}}
교환 완료.
이 기능은 요소가 처음 로드될 때만 작동하며 이후 변경 시에는 작동하지 않습니다.의 경우, 원하는 대로 동작하지 않을 수 있습니다.$digest
플레이스 홀더를 처음 교체한 후에도 계속 발생합니다(데이터의 변경이 정지될 때까지 최대 10배의 비용이 발생할 수 있습니다.대부분의 사용 사례에 적합합니다.
10월 31일 오후 7시 26분(태평양 표준시):
좋아요, 이게 아마 제 마지막 업데이트일 겁니다.이 방법은 다음과 같은 사용 사례 중 99.999에 적용될 수 있습니다.
/*
* The whenReady directive allows you to execute the content of a when-ready
* attribute after the element is ready (i.e. when it's done loading all sub directives and DOM
* content). See: https://stackoverflow.com/questions/14968690/sending-event-when-angular-js-finished-loading
*
* Execute multiple expressions in the when-ready attribute by delimiting them
* with a semi-colon. when-ready="doThis(); doThat()"
*
* Optional: If the value of a wait-for-interpolation attribute on the
* element evaluates to true, then the expressions in when-ready will be
* evaluated after all text nodes in the element have been interpolated (i.e.
* {{placeholders}} have been replaced with actual values).
*
* Optional: Use a ready-check attribute to write an expression that
* specifies what condition is true at any given moment in time when the
* element is ready. The expression will be evaluated repeatedly until the
* condition is finally true. The expression is executed with
* requestAnimationFrame so that it fires at a moment when it is least likely
* to block rendering of the page.
*
* If wait-for-interpolation and ready-check are both supplied, then the
* when-ready expressions will fire after interpolation is done *and* after
* the ready-check condition evaluates to true.
*
* Caveats: if other directives exists on the same element as this directive
* and destroy the element thus preventing other directives from loading, using
* this directive won't work. The optimal way to use this is to put this
* directive on an outer element.
*/
app.directive('whenReady', ['$interpolate', function($interpolate) {
return {
restrict: 'A',
priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
link: function($scope, $element, $attributes) {
var expressions = $attributes.whenReady.split(';');
var waitForInterpolation = false;
var hasReadyCheckExpression = false;
function evalExpressions(expressions) {
expressions.forEach(function(expression) {
$scope.$eval(expression);
});
}
if ($attributes.whenReady.trim().length === 0) { return; }
if ($attributes.waitForInterpolation && $scope.$eval($attributes.waitForInterpolation)) {
waitForInterpolation = true;
}
if ($attributes.readyCheck) {
hasReadyCheckExpression = true;
}
if (waitForInterpolation || hasReadyCheckExpression) {
requestAnimationFrame(function checkIfReady() {
var isInterpolated = false;
var isReadyCheckTrue = false;
if (waitForInterpolation && $element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
isInterpolated = false;
}
else {
isInterpolated = true;
}
if (hasReadyCheckExpression && !$scope.$eval($attributes.readyCheck)) { // if the ready check expression returns false
isReadyCheckTrue = false;
}
else {
isReadyCheckTrue = true;
}
if (isInterpolated && isReadyCheckTrue) { evalExpressions(expressions); }
else { requestAnimationFrame(checkIfReady); }
});
}
else {
evalExpressions(expressions);
}
}
};
}]);
이렇게 쓰세요.
<div when-ready="isReady()" ready-check="checkIfReady()" wait-for-interpolation="true">
isReady will fire when this {{placeholder}} has been evaluated
and when checkIfReady finally returns true. checkIfReady might
contain code like `$('.some-element').length`.
</div>
물론 최적화는 가능하겠지만, 이 정도로 하겠습니다.request Animation Frame이 좋습니다.
의 문서에는 에 대해 설명하는 엔트리가 있습니다.run
★★★★
이 방법을 사용하여 인젝터가 모든 모듈 로드를 완료한 후 수행해야 하는 작업을 등록합니다.
앱 모듈이 있는 경우:
var app = angular.module('app', [/* module dependencies */]);
모듈이 로딩된 후 다음을 실행할 수 있습니다.
app.run(function() {
// Do post-load initialization stuff here
});
편집: 복구를 위한 수동 초기화
된 것은 '가 '이러다'는 것은run
DOM 가 준비되고 링크 되어 있을 때는 호출되지 않습니다. 콜은, 「」가 에 호출됩니다.$injector
에 의해 의 경우ng-app
는 모든 의존관계를 로드하고 있습니다.【DOM】【DOM】【DOM】【DOM】
수동 초기화에 대해 다시 살펴보았는데, 이것으로 충분할 것 같습니다.
내가 설명하려고 바이올린을 만들었어.
HTML은 간단합니다.
<html>
<body>
<test-directive>This is a test</test-directive>
</body>
</html>
「」가 .ng-app
DOM 조작을 하는 지시가 있어서 순서와 타이밍을 확실히 할 수 있습니다.
통상대로 모듈이 작성됩니다.
var app = angular.module('app', []);
지시는 다음과 같습니다.
app.directive('testDirective', function() {
return {
restrict: 'E',
template: '<div class="test-directive"><h1><div ng-transclude></div></h1></div>',
replace: true,
transclude: true,
compile: function() {
console.log("Compiling test-directive");
return {
pre: function() { console.log("Prelink"); },
post: function() { console.log("Postlink"); }
};
}
};
});
그럼 이번에는 '교체하다'를 .test-directive
를 달다div
test-directive
및 그 내용을 포장을 합니다.h1
.
프리링크와 포스트링크 함수를 모두 반환하는 컴파일 기능을 추가했습니다.이러한 기능이 언제 실행되는지 확인할 수 있습니다.
나머지 코드는 다음과 같습니다.
// The bootstrapping process
var body = document.getElementsByTagName('body')[0];
// Check that our directive hasn't been compiled
function howmany(classname) {
return document.getElementsByClassName(classname).length;
}
무엇을에, 가 '아까부터', '아까부터', '아까부터', '아까부터'인 .test-directive
DOM 、 1 、 DOM 、 1 。
console.log('before (should be 0):', howmany('test-directive'));
angular.element(document).ready(function() {
// Bootstrap the body, which loades the specified modules
// and compiled the DOM.
angular.bootstrap(body, ['app']);
// Our app is loaded and the DOM is compiled
console.log('after (should be 1):', howmany('test-directive'));
});
되면 전화주세요.angular.bootstrap
응용 프로그램의 루트 요소와 모듈 이름 배열이 포함되어 있습니다.
실제로 모듈에 함수를 연결하면 컴파일이 수행되기 전에 해당 함수가 실행되는 것을 볼 수 있습니다.
바이올린을 켜고 콘솔을 보면 다음과 같이 표시됩니다.
before (should be 0): 0
Compiling test-directive
Prelink
Postlink
after (should be 1): 1 <--- success!
Angular는 어플리케이션에 따라 "완료"가 다르기 때문에 페이지 로딩이 완료되었을 때 신호를 보내는 방법을 제공하지 않습니다.예를 들어, 부분적인 계층 트리가 있는 경우 하나는 다른 하나를 로드합니다."완료"는 모두 로딩되었음을 의미합니다.어떤 프레임워크라도 코드를 분석하여 모든 것이 완료되었는지 또는 여전히 대기하고 있는지 이해하는 데 어려움을 겪을 것입니다.그러기 위해서는 어플리케이션 고유의 로직을 제공하여 이를 확인하고 판단해야 합니다.
나는 각도 초기화가 완료되었을 때 평가하는 데 비교적 정확한 해결책을 생각해냈다.
지시사항은 다음과 같습니다.
.directive('initialisation',['$rootScope',function($rootScope) {
return {
restrict: 'A',
link: function($scope) {
var to;
var listener = $scope.$watch(function() {
clearTimeout(to);
to = setTimeout(function () {
console.log('initialised');
listener();
$rootScope.$broadcast('initialised');
}, 50);
});
}
};
}]);
다음 '아트리뷰트'에할 수 .body
후, 「사용할 수 없습니다」라고 을 들었습니다.$scope.$on('initialised', fn)
$digest 사이클이 더 이상 없을 때 응용 프로그램이 초기화된다고 가정하여 작동합니다.$watch는 모든 다이제스트 사이클이 호출되므로 타이머가 시작됩니다(set Timeout은 $timeout이 아니므로 새로운 다이제스트 사이클이 트리거되지 않습니다).다이제스트 사이클이 타임아웃 내에 발생하지 않는 경우는, 애플리케이션이 초기화된 것으로 간주됩니다.
satchmoruns 솔루션만큼 정확하지는 않지만(다이제스트 사이클이 타임아웃보다 오래 걸릴 수 있음) 제 솔루션에서는 모듈을 추적할 필요가 없기 때문에 관리가 훨씬 쉬워집니다(특히 대규모 프로젝트의 경우).어쨌든, 제 요구 사항에 충분히 맞는 것 같네요.도움이 됐으면 좋겠다.
Angular UI 라우터를 사용하는 경우,$viewContentLoaded
"$viewContentLoaded - 뷰가 로드되고 DOM이 렌더링된 후 실행됩니다.뷰의 '$scope'가 이벤트를 내보냅니다." - 링크
$scope.$on('$viewContentLoaded',
function(event){ ... });
JQuery에서 각도의 DOM 조작을 관찰하고, 앱의 피니시를 설정했습니다(예를 들어 앱 추출에 필요한 사전 정의되고 만족스러운 상황).예를 들어 ng-repeater가 7개의 결과를 낼 것으로 기대하며, 그 목적을 위해 setInterval을 사용하여 관찰 기능을 설정합니다.
$(document).ready(function(){
var interval = setInterval(function(){
if($("article").size() == 7){
myFunction();
clearInterval(interval);
}
},50);
});
ngRoute 모듈을 사용하지 않는 경우, 즉 $viewContentLoaded 이벤트가 없습니다.
다른 지시 방법을 사용할 수 있습니다.
angular.module('someModule')
.directive('someDirective', someDirective);
someDirective.$inject = ['$rootScope', '$timeout']; //Inject services
function someDirective($rootScope, $timeout){
return {
restrict: "A",
priority: Number.MIN_SAFE_INTEGER, //Lowest priority
link : function(scope, element, attr){
$timeout(
function(){
$rootScope.$emit("Some:event");
}
);
}
};
}
Trusktr의 답변에 따르면 우선순위가 가장 낮습니다.또한 $timeout을 사용하면 Angular는 콜백을 실행하기 전에 이벤트 루프 전체를 실행합니다.
$rootScope는 응용 프로그램의 모든 범위에 디렉티브를 배치하고 필요한 청취자에게만 알릴 수 있기 때문에 사용됩니다.
$rootScope($rootScope 。$emit은 모든 $rootScope에 대해 이벤트를 실행합니다.$on 청취자만.흥미로운 부분은 $rootScope입니다.$broadcast는 모든 $rootScope에 통지합니다.$140 뿐만 아니라 $140도 있습니다.$on 청취자 소스
Angular 팀과 이 Github 문제에 따르면:
ng-view와 ng-include-include로 각각 출력되는 $viewContentLoaded와 $includeContentLoaded 이벤트가 있습니다.컴파일이 끝나면 바로 알 수 있다고 생각합니다.
이를 통해 현재 신뢰할 수 있는 방법은 불가능할 것으로 보입니다.그렇지 않으면 Angular는 즉시 이벤트를 제공했을 것입니다.
앱 부트스트래핑은 루트 범위에서 다이제스트 사이클을 실행하는 것을 의미하며 다이제스트 사이클이 완료된 이벤트도 없습니다.
Angular 2 설계 문서에 따르면:
여러 다이제스트가 있기 때문에 모델이 안정적이라는 것을 확인하고 구성 요소에 알릴 수 없습니다.이는 통지가 데이터를 추가로 변경하여 바인딩 프로세스를 재시작할 수 있기 때문입니다.
이에 따르면 이것이 불가능하다는 점도 Angular 2의 개서를 결정한 이유 중 하나이다.
루팅을 통해 들어온 주요 부분 이후에 로딩되는 파편이 있었습니다.
된 후에 디렉티브를 명령어를 할 수 것을 되었습니다.ngIf
상위 부분 컨트롤러:
$scope.subIsLoaded = function() { /*do stuff*/; return true; };
하위 부분의 HTML
<element ng-if="subIsLoaded()"><!-- more html --></element>
서버측 데이터(JSP, PHP)로 JS를 생성하고 싶다면 컨트롤러가 로드될 때 자동으로 로딩되는 서비스에 로직을 추가할 수 있습니다.
또, 모든 디렉티브의 컴파일/링크가 완료되었을 때에 대응하고 싶은 경우는, 상기의 적절한 제안 솔루션을 초기화 로직으로 추가할 수 있습니다.
module.factory('YourControllerInitService', function() {
// add your initialization logic here
// return empty service, because it will not be used
return {};
});
module.controller('YourController', function (YourControllerInitService) {
});
이것들은 모두 훌륭한 솔루션입니다만, 현재 루팅을 사용하고 있는 경우는, 이 솔루션이 가장 간단하고 최소한의 코드의 필요량이라는 것을 알 수 있습니다.루트를 트리거하기 전에 'resolve' 속성을 사용하여 확약이 완료될 때까지 기다립니다.
$routeProvider
.when("/news", {
templateUrl: "newsView.html",
controller: "newsController",
resolve: {
message: function(messageService){
return messageService.getMessage();
}
}
})
전체 문서를 보려면 여기를 클릭하세요 - Credit to K.스콧 앨런
내가 이 예시로 너를 도울 수 있을지도 몰라.
커스텀 팬시 박스에서 나는 보간된 값을 가진 내용을 보여준다.
서비스에서는, 「오픈」팬시 박스 방식으로, 나는 한다.
open: function(html, $compile) {
var el = angular.element(html);
var compiledEl = $compile(el);
$.fancybox.open(el);
}
$120은 컴파일된 데이터를 반환합니다.컴파일된 데이터를 확인할 수 있습니다.
언급URL : https://stackoverflow.com/questions/14968690/sending-event-when-angularjs-finished-loading
'programing' 카테고리의 다른 글
SQL 문을 sargable로 하는 것은 무엇입니까? (0) | 2023.04.08 |
---|---|
버튼을 클릭하면 애니메이션 로드 표시 (0) | 2023.04.03 |
응답 입력 onChange 지연 (0) | 2023.04.03 |
Woocommerce 3에서 환불된 주문 및 환불된 주문 항목 세부 정보 확인 (0) | 2023.04.03 |
특정 필드가 존재하는 경우 잭슨 다형성 역직렬화를 사용하여 서브타입으로 시리얼화할 수 있습니까? (0) | 2023.04.03 |