AngularJS: директива изолирует область действия — переменная области не определена

Пожалуйста, кто-нибудь может объяснить мне, почему переменная области видимости attrDir видна, а oneWay нет? Я думал, что scope: {} тоже изолирован.

angular.module('test', []);

angular.module('test').directive('attrDir', attrDir);

function attrDir(){
    return {

        scope: true,

        link: function(scope){
          scope.hello = 'attrDir';
        }

    };
}

angular.module('test').directive('oneWay', oneWay);

function oneWay(){
    return {

        scope: {
          data: '<?'
        },

        link: function(scope){
          scope.hello = 'oneWay';  
        }

    };
}

hello будет отображаться только в attr-dir.

<attr-dir>
  <span>{{hello}}</span>
</attr-dir>
<one-way>
  <span>{{hello}}</span>
</one-way>

Вот плункер: https://plnkr.co/edit/2CM4vVRshWuJvaBj2q8T?p=preview

Спасибо.


person Kindzoku    schedule 10.03.2017    source источник
comment
Следует отметить, что ни один из ответов не отвечает на вопрос правильно.   -  person Estus Flask    schedule 11.03.2017
comment
Эстус прав - one way !== isolated scopes.   -  person lin    schedule 11.03.2017
comment
@lin, см. правильный ответ здесь   -  person Max Koretskyi    schedule 11.03.2017
comment
Сила теперь с Киндзуко.   -  person lin    schedule 11.03.2017


Ответы (4)


Во-первых, то, что вы наблюдаете, не имеет ничего общего с привязкой <.

Проблема в том, что выражение {{hello}} внутри обеих директив не является частью шаблона этих директив. И для таких элементов правила привязки другие.

Angular автоматически создает функции ссылок для {{hello}} выражений. Но области, в которых оцениваются эти функции ссылок, в ваших случаях разные.

То, что вы, вероятно, ожидали, это:

            rootScope
         /             \
        /               \
attr-dir-new-scope  one-way-isoloate-scope
      /                   \
     /                     \
{{hello}}               {{hello}}

Однако, согласно этому комментарию в исходном коде:

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

реальная картина такова:

             root scope
         /             \    \
        /               \    \
attr-dir-new-scope       \    one-way-isoloate-scope
      /                   \
     /                     \
{{hello}}               {{hello}}

Итак, в вашем примере первая директива <attr-dir> не создает изолированную область, а создает новую область, поэтому при связывании angular передает эту новую область как функции связывания вашей директивы:

link: function(scope){
     scope.hello = 'attrDir';
}

и к функции связывания, созданной для выражения {{hello}}. Вот почему, когда вы добавляете значение в функцию связывания, оно становится доступным в функции связывания выражений.

Но ваша вторая директива <one-way> создает изолированную область, и, согласно комментарию, который я упомянул выше, функция связывания директивы получает изолированную область действия, как и должна, но функция связывания выражение получает другую область (корневую область в вашем примере). Итак, вы добавляете значение hello в разные области. Вот почему значение не определено.

person Max Koretskyi    schedule 11.03.2017
comment
Можете ли вы показать нам, как ваша предполагаемая директива <one-way реализует изолировать область с помощью <? - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, >? не реализует изолированную область, изолированная область реализуется путем указания объекта для свойства scope в объекте определения директивы - person Max Koretskyi; 11.03.2017
comment
Если это так, что означает <?? - person Gangadhar JANNU; 11.03.2017
comment
Кстати, это не >?, ОП пробовал <? в своей директиве - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, у меня сейчас нет времени. Создайте вопрос, и я предоставлю ответ там позже. Это <, см. здесь в это регулярное выражение @&<. ? просто говорит, что это необязательно - person Max Koretskyi; 11.03.2017
comment
@ Максимум, я знаю, что означает ?. Мы не можем предположить, что есть в исходном коде angular, однако мы отвечаем на то, что спрашивает OP. В вопросе это data: '<?' - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, я по ошибке использовал >? в своем комментарии. Нет такой привязки - person Max Koretskyi; 11.03.2017
comment
Я знаю, что нет ничего лучше >? - person Gangadhar JANNU; 11.03.2017

Обе области действия: true и scope:{} создадут дочернюю область для директивы. Но,

scope:true прототипически наследует свойства от родителя (скажем, контроллера, которому подчиняется директива), где asscope:{} не наследует свойства от родителя и, следовательно, называется изолированным

Так как oneWay — это директива изолированной области действия, и вы не передаете приветствие, поэтому оно не определено в HTML.

person Pankaj Kumar Singh    schedule 11.03.2017

Если область не указана, это общая область. Если область действия указана как true, это наследуемая область. Если область действия указана в фигурных скобках, это изолированная область.

Лучший способ визуализировать области — использовать операторы console.log в функциях ссылок, например так:

link: function(scope) {          
      scope.hello = 'attrDir';
      console.log('scope in attrDir: ', scope);
    }

    link: function(scope) {          
          scope.hello = 'oneWay';
          console.log('scope in oneWay: ', scope);
        }

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

__proto__:Scope 

тогда как второй - это объект со своей собственной областью (используя фигурные скобки, вы дали ему изолированную область)

__proto__:Object
person Latin Warrior    schedule 11.03.2017

Поскольку вы реализуете привязки компонентов в директиве.

Символ ‹ обозначает односторонние привязки, которые доступны с версии 1.5.

Если вы хотите показать компонент hello в one-way, вам следует изменить реализацию, как показано ниже:

HTML

 <one-way hello="$ctrl.hello">
      <span>{{$ctrl.hello}}</span>
    </one-way>

JS

angular.module('test').component('oneWay', {
  bindings:{
    hello:'='
  },
  controller: function() {
    this.hello = 'oneWay';
  }
});

Демо

plnkr

person Gangadhar JANNU    schedule 11.03.2017
comment
Итак, вы говорите, что directive с использованием < становится компонентом под капотом? - person Kindzoku; 11.03.2017
comment
@Киндзоку. Я говорил, что в директиве нет ничего похожего на привязку <. Если вы хотите использовать его, вы должны использовать его в component, который представлен в angular 1.5. - person Gangadhar JANNU; 11.03.2017
comment
Как это отвечает на вопрос? Даже если нет привязки data: '<?', все равно будет. - person Estus Flask; 11.03.2017
comment
@эстус. OP пытался использовать <, который не представлен в привязках директив. поэтому я предложил ему использовать компонент, если он хочет реализовать привязки < - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, твой ответ неверен. см. правильный ответ здесь - person Max Koretskyi; 11.03.2017
comment
@Kindzoku, см. правильный ответ здесь - person Max Koretskyi; 11.03.2017
comment
@Maximus Вы, вероятно, объяснили эту концепцию в другом контексте. То, что вы объяснили по-другому, не означает, что другие ответы неверны. OP спросил почему переменная области видимости attrDir видна, а oneWay нет? и я объяснил в контексте привязок компонентов angular 1.5. Поскольку OP использует < в директиве, которой не существует, я предложил ему использовать <. - person Gangadhar JANNU; 11.03.2017
comment
@all перед голосованием просто упомяните свой контекст, чтобы я его рассмотрел - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, angular 1.5 component bindings применяются к шаблонам директив, и ни одна директива в случае OP не использует шаблоны. Кроме того, символ < используется и для директив, так как компонент под капотом является директивой. И в-третьих, OP использует версию 1.5 в своем примере. - person Max Koretskyi; 11.03.2017
comment
Если это причина, можете ли вы показать мне, как мы можем реализовать < в директивах, потому что я действительно не уверен в этом - person Gangadhar JANNU; 11.03.2017
comment
@GangadharJannu, проверьте этот планкер, чтобы увидеть, как < используется в директивах. Кроме того, вы можете увидеть здесь этот компонент - просто причудливая директива. - person Max Koretskyi; 11.03.2017