Подтвердить что ты не робот

Confused об Angularjs, заключаемых и изолирующих областях и привязках

Я изо всех сил пытаюсь понять масштаб моделей и их привязки в отношении директив, которые имеют ограниченный охват.

Я понимаю, что ограничение области действия директивы означает, что контроллер. $scope и directive.scope уже не то же самое. Однако я смущен тем, как размещение моделей в шаблоне директивы или в html влияет на привязку данных. Я чувствую, что мне не хватает чего-то очень фундаментального и двигаться дальше. Мне нужно это понять.

Возьмите следующий код (здесь сценарий: http://jsfiddle.net/2ams6/)

JavaScript

var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
});
app.directive('testel', function(){
    return {
        restrict: 'E',
        scope: {
            title: '@'
        },
        transclude: true,
        template:   '<div ng-transclude>'+
                    '<h3>Template title: {{title}}</h3>' +
                    '<h3>Template data.title:{{data.title}}</h3>' +
                    '</div>'
    }    
}); 

HTML

<div ng-app='app'>
    <div ng-controller="Ctrl">
        <input ng-model="data.title">
        <testel title="{{data.title}}">
            <h3>Transclude title:{{title}}</span></h3>
            <h3>Transclude data.title:{{data.title}}</h3>
        </testel>
    </div>
</div>

Только модель обновляет {{title}} внутри шаблона и {{data.title}} в переходе. Почему не {{title}} в переходе и {{data.title}} в шаблоне?

Перемещение ввода в так называемый переход (скрипка здесь: http://jsfiddle.net/eV8q8/1/):

<div ng-controller="Ctrl">
    <testel title="{{data.title}}">
        <input ng-model="data.title">
         <h3>Transclude title: <span style="color:red">{{title}}</span></h3>

         <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>

    </testel>
</div>

теперь означает, что только transclude {{data:title}} обновляется. Почему бы не создать шаблон {{title}} или {{data.title}}, а также не перевести {{title}}?

И, наконец, перемещение ввода внутри шаблона, как это (скрипка здесь: http://jsfiddle.net/4ngmf/2/):

template: '<div ng-transclude>' +
            '<input ng-model="data.title" />' +
            '<h3>Template title: {{title}}</h3>' +
            '<h3>Template data.title: {{data.title}}</h3>' +
            '</div>'

Теперь означает, что обновляется только шаблон {{data.title}}. Снова, почему бы не остальные 3 привязки?

Надеюсь, что есть что-то очевидное, смотрящее мне в лицо, и я скучаю по нему. Если вы позволите мне получить это, я куплю вам пиво или дам вам несколько очков или что-нибудь еще. Большое спасибо.

4b9b3361

Ответ 1

Ваши скрипты создают три области:

  • область, связанная с контроллером Ctrl, из-за ng-controller
  • директива transcluded scope, из-за transclude: true
  • директива изолирует область видимости, из-за scope: { ... }

В fiddle1, прежде чем вводить что-либо в текстовое поле, мы имеем следующее:

enter image description here

Область 003 - область, связанная с контроллером. Поскольку мы еще не вводили текст в текстовое поле, нет свойства data. В области выделения 004 мы видим, что было создано свойство title, но оно пустое. Он пуст, поскольку родительская область еще не имеет свойства data.title.

После ввода my title в текстовое поле, мы теперь имеем:

enter image description here

Область контроллера 003 теперь имеет новое свойство объекта data (поэтому оно окрашено в желтый цвет), у которого свойство title теперь установлено на my title. Поскольку свойство scope изоляции title является однонаправленной привязкой к интерполированному значению data.title, оно также получает значение my title (значение цветно желтое, потому что оно изменилось).

Заданная область прототипа наследуется из области действия контроллера, поэтому внутри заключенного HTML angular может следовать цепочке прототипов и находить $scope.data.title в родительской области (но $scope.title там не существует).

Область выделения имеет доступ только к своим собственным свойствам, поэтому только свойство title.

В fiddle2 перед вводом мы имеем ту же картинку, что и в скрипке.

После ввода my title:

enter image description here

Обратите внимание, где появилось новое свойство data.title - на закрытой области. Область выделения по-прежнему ищет data.title в области контроллера, но ее не существует на этот раз, поэтому ее значение свойства title остается пустым.

В fiddle3 перед вводом мы имеем то же изображение, что и в fiddle1.

После ввода my title:

enter image description here

Обратите внимание, где появилось новое свойство data.title - в области изоляции. Ни одна из других областей не имеет доступа к области изоляции, поэтому строка my title больше не будет отображаться.


Обновление для angular v1.2:

С изменением eed299a angular теперь очищает точку перехода перед тем, как перекрыть, поэтому части Template title: ... и Template data.title: ... t, если вы не измените шаблон таким образом, чтобы ng-transclude был сам по себе, например:

'<h3>Template title: <span style="color:red">{{title}}</span></h3>' +
'<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' +
'<div ng-transclude></div>'

В приведенном ниже обновлении для angular v1.3 это изменение шаблона было сделано.


Обновление для angular v1.3 +:

Поскольку angular v1.3, transcluded scope теперь является дочерним элементом области выделения директивы, а не дочерним элементом области контроллера. Итак, в скрипке1, прежде чем мы набираем что-нибудь:

enter image description here

Изображения в этом обновлении рисуются с помощью инструмента Peri $scope, поэтому изображения немного отличаются. @ указывает, что у нас есть свойство scope изоляции, которое использует синтаксис @, а розовый фон означает, что инструмент не смог найти ссылку на предка для сопоставления (что верно, поскольку мы ничего не вводили в в текстовое поле еще).

После ввода my title в текстовое поле, мы теперь имеем:

enter image description here

Изолировать свойства, которые используют привязку @, всегда будет показывать результат интерполированной строки в области выделения после символа @. Peri $scope также смог найти это точное строковое значение в области предков, поэтому он также показывает ссылку на это свойство.

В скрипте 2 перед вводом мы имеем ту же картинку, что и в скрипке.

После ввода my title:

enter image description here

Обратите внимание, где появилось новое свойство data.title - на закрытой области. Область выделения по-прежнему ищет data.title в области контроллера, но ее не существует на этот раз, поэтому ее значение свойства title остается пустым.

В fiddle3 перед вводом мы имеем то же изображение, что и в fiddle1.

После ввода my title:

enter image description here

Обратите внимание, где появилось новое свойство data.title - в области изоляции. Несмотря на то, что транскодированная область доступа имеет доступ к области изоляции через отношение $parent, она не будет выглядеть там для title или data.title - она ​​будет выглядеть только в области контроллера (т.е. Она будет следовать за прототипом наследование), а область управления не имеет указанных свойств.

Ответ 2

После прочтения всех представленных ответов, в том числе Mark fair schematics, это мое понимание сферы действия и ее наследования по моему вопросу. Я был бы признателен за комментарии о том, где эта диаграмма падает, чтобы я мог обновить ее соответствующим образом. Надеюсь, это просто дает другое представление о том, что Марк представил:

Scope inheritance

Ответ 3

Хорошо спросил, кстати! Надеюсь, мой ответ будет столь же красноречивым.

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

Подводя итог, у вас есть две области:

  • Область управления, которая имеет $scope.data.title. (Неявно добавлено вашим элементом input)
  • Область действия директивы, которая имеет $scope.title.

При изменении контроллера $scope.data.title также изменяется директива $scope.title.

У вас также есть два раздела HTML, транслируемый и шаблон. Что происходит, так это то, что переведенный HTML находится в области контроллера, а HTML-шаблон находится в области действия директивы. Таким образом, транслируемый HTML ничего не знает о title, и область шаблона ничего не знает о data.title

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

Шаблоны директив, с другой стороны, будут иметь доступ только к области действия директивы.

Я немного изменил свой код, чтобы сделать имена более понятными (тем не менее, функциональность)

http://jsfiddle.net/yWWVs/2/