Двусторонняя привязка данных с пользовательской областью действия директивы

#javascript #angularjs #scope #angularjs-directive

#javascript #angularjs #область действия #angularjs-директива

Вопрос:

Я новичок в AngularJS, и, изучая его, я наткнулся на замечательный пост о том, как области вложены и наследуются в HTML-разметке: Понимание областей

Также я просмотрел этот Plunker, чтобы понять, о чем говорится в приведенном выше сообщении.

Я создал этот JSFiddle, чтобы понять вышеупомянутые концепции.

HTML:

 <body ng-app="myApp">
    <h1>Hello AngularJS!</h1>
    <div ng-controller="myCtrl">{{hello}}
        <div anchor-link> 
            <a href="javascript:;">click me</a>
            <div ng-show="t.show">show me</div>
            <div ng-hide="t.show">hide me</div>
        </div>
    </div>
</body>
  

JS:

 var app = angular.module("myApp", []);

app.controller('myCtrl', function ($scope) {
    $scope.hello = 'Hello World!';
    $scope.t = {
        show: true
    };
});

app.directive('anchorLink', function () {
    return {
        restrict: 'EA',
        link: function (scope, elem, attr) {
            elem.on('click', function () {
                 scope.t.show = !scope.t.show;
            });
        }
    };
});
  

Теперь мой вопрос:

  1. Почему двусторонняя привязка данных не работает в моем fiddle? Разве область действия моей пользовательской директивы не должна наследоваться от своего родителя (т. Е. контроллера)?

  2. Если я использую $scope.t в качестве объекта в области контроллера. тогда почему он не переключает «показать мне» и «скрыть меня» divs? Я также пытался использовать scope: true в своей пользовательской директиве, но это все еще не работает.

  3. Это потому, что scope в моей функции link не наследуется прототипически?

  4. Действительно ли это изменяет $scope.t объект родительской области?

Ответ №1:

Итак, что вам нужно сделать, это:

 http://jsfiddle.net/DkFx9/
  

Здесь происходит то, что вы используете click обработчик событий jQuery для обработки события click и изменения scope переменной в обработчике. Проблема с этим заключается в том, что у angular нет способа узнать, что что-то в scope изменилось, и, следовательно, ему необходимо обновить представления.

Обычно, когда вы делаете что-то подобное, используя директиву angular like ng-click="t.show = !t.show" , angular знает, что некоторые даже произошли через angular, и запускает цикл дайджеста, чтобы выполнить грязную проверку и обновить связанные представления.

В вашем случае мы должны сообщить angular, что что-то происходит, и он должен запустить цикл дайджеста. scope.$apply берет фрагмент кода, который вы хотите выполнить, а затем просит angular запустить цикл дайджеста и обновить представления, которые необходимо обновить.

Надеюсь, это поможет.

Комментарии:

1. О!! Хорошо. Но есть ли какой-либо другой способ, кроме использования $apply? А как насчет моего 4-го вопроса. Даже если привязка данных не происходит по причинам, объясненным вами .. действительно ли значение меняется в родительской области или нет? Я думаю, да, поскольку оповещения показывают обновленное значение в обработчике событий

2. Также могу ли я изолировать область, чтобы происходило привязывание? или это не повлияет по тем же причинам, которые вы объяснили?

3. Итак, запустите JSfiddle, которым я поделился. И вы заметите, что значения действительно меняются. Значения меняются, да. И происходит привязка данных. Единственная проблема заключалась в том, что объект Javascript был изменен, но Angular не знает об этом, поэтому он не может обновлять представления и выполнять манипуляции с DOM, как того требуют ng-hide и ng-show . Итак, по сути, t объект области видимости контроллера имеет новое измененное значение, но значение не было отражено в представлении из-за того, что цикл дайджеста не был запущен.

4. Если вы изолируете область действия, то ничего не будет отражено снаружи, т. е. в области действия контроллера (потому что директива теперь имеет изолированную область действия).