Поиск…


Синтаксис

  • $ scope. $ watch (watchExpression, callback, [deep compare])
  • $ Объем. $ Дайджеста ()
  • $ Сфера. $ Применять ([ехр])

двусторонняя привязка данных

Угловая магия под капотом. он позволяет связывать DOM с реальными переменными js.

Угловой использует цикл, называемый « цикл дайджеста », который вызывается после любого изменения вызывающих переменную вызовов, которые обновляют DOM.

Например, ng-model директивы придает keyup EventListener к этому входу:

<input ng-model="variable" />

Каждый раз, когда срабатывает событие keyup , начинается цикл дайджест .

В какой-то момент цикл дайджеста выполняет повторный вызов, который обновляет содержимое этого диапазона:

<span>{{variable}}</span>

Основной жизненный цикл этого примера обобщает (очень схематично), как угловые работы ::

  1. Угловое сканирование html
    • Директива ng-model создает прослушиватель keyup на входе
    • expression внутри диапазона добавляет обратный вызов цикла digest
  2. Пользователь взаимодействует со входом
    • прослушиватель keyup запускает цикл дайджеста
    • цикл дайджеста вызывает обратный вызов
    • Содержимое диапазона обратного вызова

$ digest и $ watch

Реализация двухсторонней привязки данных для достижения результата из предыдущего примера может быть выполнена с помощью двух основных функций:

  • $ digest вызывается после взаимодействия с пользователем (привязка переменной DOM =>)
  • $ watch устанавливает обратный вызов для вызова после изменения переменной (binding variable => DOM)

Примечание: это пример демонстрации, а не фактический угловой код


<input id="input"/>
<span id="span"></span>

Нам нужны две функции:

var $watches = [];
function $digest(){
    $watches.forEach(function($w){
        var val = $w.val();
        if($w.prevVal !== val){
            $w.callback(val, $w.prevVal);
            $w.prevVal = val;
        }
    })
}
function $watch(val, callback){
    $watches.push({val:val, callback:callback, prevVal: val() })
}

Теперь мы теперь можем использовать эти функции, чтобы подключить переменную к DOM (угловой поставляется со встроенными директивами, которые сделают это для вас):

var realVar;    
//this is usually done by ng-model directive
input1.addEventListener('keyup',function(e){
    realVar=e.target.value; 
    $digest()
}, true);

//this is usually done with {{expressions}} or ng-bind directive
$watch(function(){return realVar},function(val){
    span1.innerHTML = val;
});

Вне курса, реальные реализации сложнее и поддерживают такие параметры, как какой элемент привязать и какую переменную использовать

Пример работы можно найти здесь: https://jsfiddle.net/azofxd4j/

дерево $ scope

Предыдущий пример достаточно хорош, если нам нужно связать один элемент html с одной переменной.

В действительности - нам нужно связать многие элементы со многими переменными:

<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>

Этот ng-repeat связывает 5 элементов с 5 переменными, называемыми number , с другим значением для каждого из них!


Способ углового достижения такого поведения заключается в использовании отдельного контекста для каждого элемента, который нуждается в отдельных переменных. Этот контекст называется областью.

Каждая область содержит свойства, которые являются переменными, связанными с DOM, а функции $digest и $watch реализованы как методы области.

DOM - это дерево, а переменные должны использоваться на разных уровнях дерева:

<div>
    <input ng-model="person.name" />
    <span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
</div>

Но, как мы видели, контекст (или область) переменных внутри ng-repeat отличается от контекста над ним. Чтобы решить эту проблему - угловые орудия применения как дерево.

Каждая область имеет массив дочерних элементов, а вызов метода $digest будет запускать весь метод $digest своего $digest метода.

Таким образом - после изменения ввода - $digest вызывается для области div, которая затем запускает $digest для своих 5 детей - который обновит его содержимое.


Простая реализация для области видимости может выглядеть так:

function $scope(){
    this.$children = [];
    this.$watches = [];
}

$scope.prototype.$digest = function(){
    this.$watches.forEach(function($w){
        var val = $w.val();
        if($w.prevVal !== val){
            $w.callback(val, $w.prevVal);
          $w.prevVal = val;
        }
    });
    this.$children.forEach(function(c){
        c.$digest();
    });
}

$scope.prototype.$watch = function(val, callback){
    this.$watches.push({val:val, callback:callback, prevVal: val() })
}

Примечание: это пример демонстрации, а не фактический угловой код



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow