Scope

Scope - объект/словарь для отслеживания изменений значений переменных.

$watch - добавляет имя для отслеживания изменений

scope.$watch = function(name, callback) {
    scope.$$wached.push({  // создаем новую запись
        name: name,  // имя переменной
        value: scope[name],  // текущее значение переменной
        callback: callback  // callback
    })
}

$scan ищет изменения переменных добавленных ф-ией scope.$watch и вызывает callback-и

scope.$scan = function() {
    for(w in scope.$$wached) {  // перебираем все записи добавленные через $watch
        if(w.value != scope[w.name]) {  // значение изменилось?
            w.value = scope[w.name];  // сохраняем текущее значение
            w.callback(w.value);  // вызываем callback
        }
    }
}

Биндинг DOM к Scope

applyBindings ищет аттрибуты al-value, al-checked и т.п. и вызывает методы alight.directives.al.value, alight.directives.al.checked и т.п. В эти ф-ии передает (el, name, scope): el - элемент где найден атрибут, name - значение атрибута, scope - текущий Scope

alight.applyBindings = function(scope, dom) {
    for(attrName, attrValue in dom.attributes) {  // Перебираем атрибуты элемента
        directive = alight.directives[attrName]  // берем директиву по имени  атрибута
        directive(dom, attrValue, scope)  // вызываем директиву
    }
    for(childElement in dom.children) {  // перебираем дочерние элементы
        scope.applyBindings(scope, childElement);  // вызываем рекурсивно
    }
}

Декларативный биндинг {{name}}, applyBindings вызывает scope.$watch(name, function(value) { element.text = value })

Пример директивы

alight.directives.al.value = function(el, name, scope) {
    $(el).on('keypress', function(elementValue) {
        scope[name] = elementValue; // изменили значение
        scope.$scan()  // запустили поиск изменений
    })

    scope.$watch(name, function(newValue) {  // отслеживаем изменение переменной
        el.value = newValue;  // устанавливаем новое значение в элемент
    })
}

alight.bootstrap создает новый scope и вызывает alight.applyBindings

alight.bootstrap = function(element) {
    if(!element) element = document.querySelector('[al-app]');

    scope = new alight.Scope();
    alight.applyBindings(scope, element);
}

Пример

Как работает <div al-app> <input al-value="model"> {{model}} </div>

При вводе текста в input, срабатывает $(el).on('keypress', ...) из п.4. при этом происходит изменение значение model и вызывается $scan. $scan находит, что model был изменен и вызывает callback из п. 3.1., этот callback устанавливает новый текст из model в элемент {{model}}

comments powered by Disqus