앵귤러군의 컴포넌트는 무엇이 있고 어떻게 상호작용하는지 알아보자
Startup
- Angular는 어떻게 Hello World를 출력하는가?
- 브라우져는 HTML를 로드하고 DOM객체로 파싱한다
- DOMContentLoaded 이벤트가 발생하면 Angular 는 애플리케이션 경계를 결정해주는 ng-app 지시자를 찾는다
- ng-app으로 명시된 모듈은 $injector를 환경설정한다
- $injector는 $compile & $rootScope를 생성한다
- $compile 서비스를 통해 DOM을 컴파일하고 $rootScope와 Link를 맺는다
- ng-init 을 통해서 scope 내의 name property에 World를 할당한다
- <!doctype html>
- <html ng-app>
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- </head>
- <body>
- <p ng-init=" name='World' ">Hello {{name}}!</p>
- </body>
- </html>
- 흐름도
Runtime
- Angular와 브라우져간의 이벤트 루프를 돌며 상호 작용을 어떻게 하는가?
+ 브라우져 이벤트 루프는 이벤트 - 사용자 행위, 타이머, 서버응답에 대한 네트워크 이벤트등 - 발생을 기다린다
+ 이벤트의 콜백이 수행되고, JavaScript Context로 들어간다음 DOM 구조를 조작한다
+ JavaScript Context를 나오면 DOM 기반의 다시 그려진 화면으로 바뀐다
- 전통적인 JavaScript execution context 와 Angular execution context 동작 방식에 차이가 있다
+ Angular execution context가 하는 일 : data-binding, exception 처리, 프로퍼티 변경 감시 등등
+ $apply를 통하여 JavaScript execution context에서 Angular execution context로 들어갈 수 있다
+ $apply의 직접호출은 사용자정의 이벤트 콜백과 3th-party 라이브러리 콜백일때만 사용하고 directive에서 자동 호출된다
+ 이에 대한 자세한 이해는 다음의 블로그를 꼭 읽어보길 바란다 : AngularJS and scope.$apply Posting
- 다이어그램 이해
+ scope.$apply(stimulusFn) 호출로 Angular Execution Context로 들어가고, stimulusFN은 이안에서 수행할 일이다
+ Angular가 stimulusFn 을 수행하고 애플리케이션의 상태를 변경한다
+ Angular는 다음으로 $digest 루프로 들어가고, 이는 $evalAsync 큐와 $watch 목록을 처리하는 작은 루프이다.
+ $evalAsync는 현재 스택 프레임 외부에서 발생하는 스케쥴 잡에 사용된다
+ $watch 펑션은 변경을 감지하고 DOM에 새로운 값으로 업데이트 하는 역할을 수행한다
+ Angular 의 $digest 루프가 끝나면 Angular와 JavaScript context를 빠져나온다.
- 소스를 보고 다시 보자
+ Compilation 구간
> ng-model과 input directive는 keydown시에 listener를 <input> 태그에 설정토록 한다
> {{name}}은 $watch가 name 변경을 알 수 있게 설정토록 한다
+ Runtime 구간
> H를 입력하면 브라우져가 keydown 이벤트를 발생시킨다
> input directive는 Angular Execution Context에서 모델값 업데이트를 위하여 값의 변경을 잡아서 $apply("name = 'H';") 를 호출한다
> Angular는 모델에 name = H 를 적용한다
> $digest 루프가 시작되고 $watch 는 name property 변경을 감지한 후 DOM을 업데이트 하도록 알려준다.
> 그런후 Angular Execution Context를 빠져나오고 keydown 이벤트와 JavaScript Execution Contex를 빠져나온다
- <!doctype html>
- <html ng-app>
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- </head>
- <body>
- <input ng-model="name">
- <p>Hello {{name}}!</p>
- </body>
- </html>
Scope
- scope는 모델 변경을 감지하고 표현하기 위해 Execution context 를 제공하는 책임을 갖는다
- scopes는 DOM 구조와 가깝게 하이어라키 구조를 갖는다
- 소스보기
- <!doctype html>
- <html ng-app>
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- <script src="script.js"></script>
- </head>
- <body>
- <div ng-controller="GreetCtrl">
- Hello {{name}}!
- </div>
- <div ng-controller="ListCtrl">
- <ol>
- <li ng-repeat="name in names">{{name}}</li>
- </ol>
- </div>
- </body>
- </html>
해당 소스에 대해서 이런 구조이다
Controller
- controller는 뷰뒤에 있는 반드시 수행하는 코드이다
- controller 역할은 모델을 생성하고 콜백 메소드를 가지고 view로 퍼블리싱을 담당한다
- view는 템플릿으로 Scope의 투영체이고, Scope는 Model과 View의 연결하며 controller로 이벤트를 보낸다
- view 와 controller 분리 이유
+ controller 는 자바스크립트이고 업무적 행위를 정의한다. 또한 DOM rendering 정보가 일체 없다
+ view template은 HTML이고 형태를 선언하고 행위는 없다
- Controller가 view를 인지하지 않으므로 많은 view 에 대한 처리를 담당할 수도 있다
Model
- 모델은 화면 템플릿에 합쳐지는 데이터를 가지고 있는 일반 자바스크립트 객체이다
- Scope가 모델을 reference (참조) 하고 타입 제약을 갖지 않는다
View
- 일반적인 것은 템플릿 스트링과 모델을 합쳐서 HTML을 만들고 DOM으로 해석되어 브라우져에 표현된다
- Angular는 템플릿이 HTML이어서 바로 DOM으로 해석되고 DOM안에 directive가 템플릿 엔진인 $compile 를 통해 $watch를 설정하고 모델의 변경을 계속 감시하게 된다. 따라서 모델값과 템플릿의 re-merging할 필요가 없게 된다.
- Angular Model은 화면에 대하여 single source-of-truth 이다
- 소스 : 동시에 바뀐다
- <!doctype html>
- <html ng-app>
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- </head>
- <body>
- <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
- <input ng-model="list" ng-list> <br>
- <input ng-model="list" ng-list> <br>
- <pre>list={{list}}</pre> <br>
- <ol>
- <li ng-repeat="item in list">
- {{item}}
- </li>
- </ol>
- </div>
- </body>
- </html>
Directives
- 지시자는 HTML 을 확장하여 주고 행위를 일으키는 주체이다
+ custom attributes
+ element name
+ class name
// html
- <!doctype html>
- <html ng-app="directive">
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- <script src="script.js"></script>
- </head>
- <body>
- <div contentEditable="true" ng-model="content">Edit Me</div>
- <pre>model = {{content}}</pre>
- </body>
- </html>
// css
- div[contentEditable] {
- cursor: pointer;
- background-color: #D0D0D0;
- margin-bottom: 1em;
- padding: 1em;
- }
// js
- angular.module('directive', []).directive('contenteditable', function() {
- return {
- require: 'ngModel',
- link: function(scope, elm, attrs, ctrl) {
- // view -> model
- elm.bind('blur', function() {
- scope.$apply(function() {
- ctrl.$setViewValue(elm.html());
- });
- });
- // model -> view
- ctrl.$render = function(value) {
- elm.html(value);
- };
- // load init value from DOM
- ctrl.$setViewValue(elm.html());
- }
- };
- });
Filters
- 데이터의 변환를 담당한다
- | 파이프를 사용한다
- <!doctype html>
- <html ng-app>
- <head>
- <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
- </head>
- <body>
- <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
- Number formatting: {{ 1234567890 | number }} <br>
- array filtering <input ng-model="predicate">
- {{ list | filter:predicate | json }}
- </div>
- </body>
- </html>
Modules and Injector
- injector 는 Angular Application (ng-app) 에 하나만 존재한다
- injector는 명칭을 통해서 오브젝트 인스턴스를 찾는 방법을 제공한다
- 오브젝트 인스턴스에 대한 캐쉬를 가지고 있어서 생성된 것을 주거나 없으면 생성한다
- module 은 provider로 알려진 injector의 인스턴스 팩토리를 통해 환경 설정하는 방법이다
- 소스
- // Create a module
- var myModule = angular.module('myModule', [])
- // Configure the injector
- myModule.factory('serviceA', function() {
- return {
- // instead of {}, put your object creation here
- };
- });
- // create an injector and configure it from 'myModule'
- var $injector = angular.injector(['myModule']);
- // retrieve an object from the injector by name
- var serviceA = $injector.get('serviceA');
- // always true because of instance cache
- $injector.get('serviceA') === $injector.get('serviceA');
$
- $는 앵귤러의 오브젝트 명칭임을 나타내므로 가급적 충돌을 방지하기 위하여 $는 쓰지 말자
Backbone.js & Angular.js
- angular는 62 page 부터 시작
- 91 page : Angular Basic Service $로 시작 예) $q
- 92 page : 전역 API 예) element는 jQuery lite
<참조>
- 원문 : Developer Guide - Concepts
- 다양한 모듈들 : http://ngmodules.org/ ==> Angular안에서 Backbone사용하기
- Boostrap 연동 : http://angular-ui.github.io/
'AngularJS > Concept' 카테고리의 다른 글
[AngularJS] 개발자 가이드 - 06. 모듈 (0) | 2013.04.11 |
---|---|
[AngularJS] 개발자 가이드 - 05. 지시자(Directives) (0) | 2013.04.11 |
[AngularJS] 개발자 가이드 - 03. HTML 컴파일러 (0) | 2013.04.10 |
[AngularJS] 개발자 가이드 - 02. 시작하기 (0) | 2013.04.10 |
[AngularJS] 개발자 가이드 - 01. 개요 (0) | 2013.04.10 |