Angular’ın perde arkası (1.x)

Hana Kamer
Hana Kamer
Published in
5 min readMay 11, 2016

--

Yazılarımda amaçladığım şey, yeni öğrendiğim şeyleri tazeyken anlatıp en temeline kadar araştırmak. Bu yazımda da Angular 1.x ‘in nasıl çalıştığından ve temelinden bahsedeceğim. Her ne kadar Angular 2 çıkıyor olsa da Angular 1.x’e hemen sırtımızı dönemeyiz:)

AngularJS başlıca Google ekibi tarafından geliştirilen açık kaynak bir JS frameworkudur. MVC mimari yapısını sunar, declerative bir yaklaşım izler, moduler yapılarda yazılmayı destekler ve test aşamasını kolaylaştırır.

SPAlarda (Single Page Application) amaç, model state indeki değişikliği algılamak. Buradaki her değişiklik DOM’un yenilenmesi, re-render ve reflow gibi ağır işlemleri tetikler. Bunu her model değişitiğinde yapmaktansa değişiklikleri biriktirip belli aralıklarla tetiklemek verimliliği arttırır.

Angular MEAN stackın frontend bölümünde yer alır.

Software stack: Bir app oluşturmak için ihtiyaç duyulan bütün altyapı ve componentleri tek bir platformda birleştiren yazılım yapısıdır.

MEAN stack: Dinamik web app yapmak için kullanılan JS software stack. Elemanları:

  • MongoDB
  • Express.js
  • Angular.js
  • Node.js

AngularJS, UI ların yazılmasında declerative programlama prensibinin kullanılması gerektiğini savunan felsefe üzerine geliştirilmiştir.

  • Declerative programlamada sadece ne yapmak istenen yazılır, fakat yolu belirtilmez.
  • Imperative programlamada yapmak istenen işlemler adım adım belirtirtilir.

Angular, değer değişikliklerini data modelini yenileyecek şekilde nasıl algılar?

Angular’ın bunu nasıl yaptığını anlamak için $scope, $watch, $digest ve $apply terimlerini anlamak gerekir.

$scope

Bilgisayar biliminde scope, bir ismin bir oluşum ile ilişkilendirilebildiği (bir değişkenin, programın bağ kurulabilen kısmını oluşturması gibi) yer olarak tanımlanır.

Angular’da scope, app’in içinde yer alan değişken ve fonksiyonlara sahip olan objedir. Controller ve View arasında köprü görevi görür.

$watch

View katmanına bir değişken bağladığınız anda AngularJS bir ‘watch’ oluşturur. Watch, AngularJS’in $scope objesindeki değişkenlerin değişimlerinin izlenmesini sağlar.

$digest

Digest döngüsü, belli aralıklarla çalıştırılan bir koddur. Buradaki amaç sık sık ve gereksiz olarak tekrarlanmasını istemediğimiz ağır görevleri birleştirip öyle çalıştırmak. Bu görevlere örnek olarak DOM rendering, reflow /layout işlemlerini verebiliriz.

Digest döngüsünü, bir Angular App’inin durmadan atması gereken kalbine benzetebiliriz. Zira bu döngünün durması, Angular’ın hiç bir değişikliği algılamamasına neden olur.

Digest döngüsü, bulunduğu scope ve çocuklarının watchExpressionlarını işler, bütün watchları tek tek geçerek değişime uğramış değişken var mı diye kontrol eder. watchExpression’da şuan bulunan değer ile bir önceki değer karşılaştırılır. Değerler aynı değil ise ‘dirty’ olarak işaretlenir.

watchExpressions

Her $digest döngüsü içerisinde watchExpression var. wacthExpression, her döngüde o an izlemekte olduğu değeri döner(dirty checking).

Eğer şu anki ve önceki değer aynı değil ise karşılık gelen listener tetiklenir.

listener: Belli bir aksiyondan sonra tetiklenmesi istenen belirli fonksiyonlar vardır. Bu fonsiyonların, kendilerini tetikleyecek olan aksiyonu beklemesine ‘listen’ (dinlemek) denir.

Bir listenerın tetiklenmesi ile modelde oluşan değişiklik başka listenerlerın tetiklenmesine sebep olabilir. Bu nedenle watcherlar yeni watcher oluşumu durana kadar tekrar tekrar çalıştırılır.

$apply

Bunu Angular dünyası ile dış dünya arasındaki bağlantı servisi olarak düşünebiliriz. $apply, $digest metodunu çağırır.

Tarayıcının DOM eventleri Angular’ın dışından tetiklendiği zaman $apply kullanılmalı (JQuery gibi third party kütüphaneleri kullanacağınız zaman Angular’ın bunlar aracılığı ile oluşan değişimleri izleyebilmesi için apply metoduna gömmeniz gerekir ki Angular bunlardan haberdar olsun.).

Özet

resim kaynağı için link

Artık bu 3 terimi tanımladıktan sonra süreci şöyle özetleyebiliriz:

  • UI’a değişken bağladığınız anda bu değişken watcher ratafından izlenmeye başlanır.
  • Angular, $scope.$digest() fonksiyonunu çağırır ve $digest döngüsünü başlatır.
  • Döngü sırasında bütün watcherlar kontrol edilir.
  • Değişkenlerde değişiklik varsa ‘dirty’ olarak işaretlenir; yoksa döngü tekrarlanır ve değişen watcher var mı diye kontrol edilir.
  • Değişen watcher yoksa listener tetiklenir, varsa döngü tekrarlanır.
  • Döngü en az 2, en fazla da 10 defa tekrarlanır ki sonsuz döngüye girmek engellensin.

Nasıl çalışır?

Angular’da karşımıza çıkan temel konseptleri inceledim bu bölümde.

Angular frameworkunun çalışma prensibine göre Angular, önce HTML sayfasını okur ve HTML tag özelliklerini input ve outputlar ile ilişkilendirilmiş direktifler olarak yorumlar.

HTML derleyici

Anguların HTML derleyicisi tarayıcıya yeni HTML yazım şekli (syntax) öğretir. Bu derleyici HTML elemanlarına davranış bağlayarak özelleşmiş HTML elemanları ve özelliklerinin oluşmasını sağlar. Angular, bu davranış uzantıları olan elemanlara direktif adını verir.

Derleyici iki işlem gerçekleştirir:

  1. derleme: Bütün DOM’u yukarıdan aşağı tarayarak direktifleri toplar ve sonuçta bir linking fonksiyonu oluşturur.
  2. Bütün direktifler toplandıktan sonra bunlar önceliklerine göre sınıflandırılır.
    # tek bir DOM elementine bağlı birden fazla direktif bulunması durumunda bunlar önceliklerine göre işlenir
  3. link: Topladığı direktifleri scope’a bağlayarak canlı View oluşturma. Canlı olmasından anlaşılacağı üzere scope Model’de yapılan değişiklikler View’da hemen yasıtılır ve aynı şekilde View’da yapılan değişiklik de scope modeline yansıtılır. DOM’un listenerlar ile, scope’un da $watch ile ayarlanıp ikisinin birbiri ile senkonize halde tutulmasıdır.

Module

Module, Angular app’ı parçası olarak tanımlanabilir.

Direktif (Directive)

DOM’un işlenmesi için kullanılan kod parçaları olarak tanımlanırlar. Bunlar DOM elemanlarında yer alan ve Angular’ın HTML derleyicisini hedef alan işaretlerdir. Derleyici, direktif ile kaşılaştığında; Angular’a, bulundugu eleman için tanımlanmış olan davranışın atanmasını söyler. Başka bir deyişle direktif, DOM’da derleyici ile karşılaştığında çalıştırılan fonksiyondur.

Direktifler HTML elemanlarının isimlerinde, class isimlerinde, özelliklerinde ve yorumlarında yer alabilir.

Angular’ın önceden tanımlanmış direktifleri olduğu gibi kendimiz de custom direktif ekleyebiliriz.

Angular 1.5 ile beraber Component yapısı Angular 1.x e girmiş oldu. Componentlar direktiflerin özel bir çeşidi olup, daha basit bir yazım şekline sahiptir. Componente dayalı yapı oluşturmayı kolaylaştırır ve DOM’a müdahale etme hedefiniz olmadığı sürece component kullanımı önerilir.

Servis

Servisler, obje dönen callback fonksiyonlardır. Bunlar app’in farklı katmanlarında aynı dataya ulaşımasını ve değiştirilebilmesini sağlar. Servisler, direktif, controller ve filtreler tarafından kullanılabilir. Bu şekile kod moduler yapısını korur ve sorumlulukların ayrıştırılması (separation of concerns) felsefesine bağlı kalır.

Sonuç olarak domainler arası data paylaşmak istediğimizde servis kullanmak kodun temiz ve moduler kalmasını destekleyen bir yaklaşım olur.

Controller

Controller, model datasının $scope aracılığı ile View’a bağlanmasından sorumludur. Ancak datanın çekilmesi ve değiştirilmesi aşamasından sorumlu değildir. Bunun için servisler kullanılır.

Angular’da controller, Angular scope’unu genişletmek için kullanılan constructor fonksiyonu olarak tanımlanır.

constructor fonksiyonu: Javascrip’de yeni obje oluşturmak için ‘new’ ile çağrılan fonksiyonlardır. Aynı özellik ve metodlara sahip benzer objeler oluşturmak için kullanılırlar.

Controller, ng-controller direktifi kullanarak DOM’a bağlandığında; Angular, tanımlanan Controller’ın constructor fonksiyonu ile yeni bir Controller objesi oluşturur.

Örnek olarak bir Controllerı şöyle oluşturabiliriz:

var myApp = angular.module('myApp',[]);myApp.controller('MainController', ['$scope', function($scope) {
$scope.greeting = 'Hello Angular!';
}]);

Bu Controller’ın ‘greeting’ özelliği ‘Hello Angular!’ değerine sahip olsun.

Bu Controller’ı DOM’a bağlamak istersek:

<div ng-controller="MainController">
{{ greeting }}
</div>

şeklinde ng-controller direktifi aracılığı ile Controller bağlanır. Böylece artık MainController’da yer alan ‘greeting’e ulaşabiliriz.

--

--