Путать о AngularJS раскрываемый и изолировать областей & Привязок


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

Я понимаю, что ограничение области действия директивы означает, что контроллер.$область и директива.объем не то же самое. Однако я смущен тем, как размещение моделей либо в шаблоне директивы, либо в 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 привязки?

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

3 55

3 ответа:

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

  1. область, связанная с контроллером Ctrl из-за ng-controller
  2. директива вышла за пределы области видимости, из-за transclude: true
  3. директива изолировать область, из-за scope: { ... }

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

enter image description here

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

после ввода my title в текстовое поле, теперь у нас есть:

enter image description here

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

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

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

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

после ввода 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 Угловое теперь очищает точки передача до transcluding, поэтому Template title: ... и Template data.title: ... детали не будут отображаться, если вы не измените шаблон таким образом, что 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 теперь является дочерним элементом области изоляции директивы, а не дочерним элементом области контроллера. Итак, в fiddle1, прежде чем мы наберем что угодно:

enter image description here

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

после ввода my title в текстовое поле, теперь у нас есть:

enter image description here

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

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

после ввода 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 -- он будет выглядеть только в области контроллера (т. е. он будет следовать прототипному наследованию), а область контроллера не имеет этих свойств.

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

Scope inheritance

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

ответ, как раскрываемый элементы, сделать их объем.

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

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

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

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

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

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

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

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