Понимание опции transclude определения директивы?


195

Я думаю, что это одна из самых сложных концепций для меня с помощью директивы angularjs.

В документе http://docs.angularjs.org/guide/directive говорится:

transclude - компилирует содержимое элемента и делает его доступным для директивы. Обычно используется с ngTransclude. Преимущество включения состоит в том, что функция связывания получает функцию включения, которая предварительно привязана к правильной области видимости. В типичной настройке виджет создает изолированную область видимости, но включение не дочерний, а родственный элемент изолированной области видимости. Это позволяет виджету иметь частное состояние, а включение может быть привязано к родительской (предизолятной) области видимости.

  • true - включить содержание директивы.
  • 'element' - включить весь элемент, включая любые директивы, определенные с более низким приоритетом.

Как transcludeправило, используется с ngTransclude. Но образец из документа ngTransclude вообще не использует ngTranscludeдирективу.

Я хотел бы несколько хороших примеров, чтобы помочь мне понять это. Зачем нам это нужно? Что это решает? Как это использовать?


К вашему сведению ... ссылка работает, по крайней мере, сейчас
Сэнди

Ответы:


518

Рассмотрим директиву myDirective в элементе, и этот элемент включает в себя некоторый другой контент, скажем:

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Если myDirective использует шаблон, вы увидите, что содержимое <div my-directive>будет заменено вашим шаблоном директивы. Итак, имея:

app.directive('myDirective', function(){
    return{
        template: '<div class="something"> This is my directive content</div>'
    }
});

приведет к этому рендеру:

<div class="something"> This is my directive content</div> 

Обратите внимание, что содержимое вашего исходного элемента <div my-directive> будет потеряно (или, точнее, заменено). Итак, попрощайтесь с этими приятелями:

<button>some button</button>
<a href="#">and a link</a>

Итак, что, если вы хотите сохранить себя <button>...и <a href>...в DOM? Вам понадобится то, что называется transclusion. Концепция довольно проста: включить контент из одного места в другое . Так что теперь ваша директива будет выглядеть примерно так:

app.directive('myDirective', function(){
    return{
        transclude: true,
        template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
    }
});

Это сделало бы:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 

В заключение, вы в основном используете transclude, когда хотите сохранить содержимое элемента, когда используете директиву.

Мой пример кода здесь . Вы также можете извлечь выгоду из просмотра этого .


12
Похоже, они немного изменили функциональность. По крайней мере, в версии> = 1.2.9. Содержимое шаблона не добавляется к отображаемому содержимому. Смотрите ответ @ TechExplorer ниже
Tarjei Romtveit

20
Очень, очень хороший ответ. Значительно выше нормы. У вас есть хорошие примеры, и ваше «это мое директивное содержание» очень облегчило чтение в визуализированной версии. Я не понимаю, почему Angular использует сложную терминологию и понятия, а затем не включает в себя такие простые для понимания примеры, как ваша. +2
бесплатно все

Кто-нибудь знает, может ли включенный контент ссылаться на изолирующие поля директивы? Выше сказано, что включение - это брат, а не ребенок, из изолированной области ... поэтому я предполагаю, что это не может - но мне было интересно, может ли кто-то подтвердить или сообщить мне, если это возможно
Саймон Грин

@UladzimirHavenchyk спасибо, они переместили видео в другое место. Я исправил ссылку соответственно.
odiseo

4
@odiseo, не могли бы вы написать ВСЕ англоязычные документы на простом и понятном английском, как это! + много 1
Дэн Ходсон

76

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

Содержимое элемента с помощью ng-transclude не добавляется, а полностью заменяется.

Таким образом, в приведенном выше примере вы могли бы добиться с помощью transclude:

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>

и нет

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Спасибо.


Для получения дополнительной информации об измененном поведении в Angular 1.2 см. Change eed299a .
Марк Райкок

37

То, что TechExplorer говорит, верно, но вы можете иметь оба содержимого, включив в свой шаблон простой тег контейнера (например, div или span) с атрибутом ng-transclude. Это означает, что следующий код в вашем шаблоне должен включать все содержимое

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>

5
Это была ключевая информация, которая отсутствовала в других ответах
Матеус

4
Этот ответ добавляет так много информации. ng-transcludeявляется атрибутом, который действует как заполнитель, внутри которого будет размещаться включенный контент.
BeingSuman

5

Из вики:

«В информатике включение - это включение части или всего электронного документа в один или несколько других документов посредством ссылки».

Я хотел бы добавить другое использование для transclusion, и это - то, что это изменяет порядок выполнения функций компиляции и ссылки родительских и дочерних директив. Это может быть полезно, когда вы хотите скомпилировать дочерний DOM перед родительским DOM, поскольку родительский DOM, возможно, зависит от дочернего DOM. Эта статья более углублена и проясняет это очень хорошо!

http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives-part-2-transclusion/


5

Обновленные AngularJS 1.6.6 документации теперь есть лучшее объяснение.

Transclude используется для создания директивы, которая охватывает другие элементы

Иногда желательно иметь возможность передавать весь шаблон, а не строку или объект. Допустим, мы хотим создать компонент «диалоговое окно». Диалоговое окно должно быть в состоянии обернуть любой произвольный контент.

Для этого нам нужно использовать опцию transclude . Обратитесь к примеру ниже.


script.js

angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog', function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    templateUrl: 'my-dialog.html',
    link: function(scope) {
      scope.name = 'Jeff';
    }
  };
});

index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>

мой-dialog.html

<div class="alert" ng-transclude></div>

Скомпилированный вывод

<div ng-controller="Controller" class="ng-scope">
  <my-dialog class="ng-isolate-scope"><div class="alert" ng-transclude="">Check out the contents, Tobias!</div></my-dialog>
</div>

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

Это показано в предыдущем примере. Обратите внимание, что мы добавили функцию link в script.js, которая переопределяет имя как Jeff. Обычно мы ожидаем, что {{name}} будет Джефф. Однако в этом примере мы видим, что привязка {{name}} по-прежнему является Tobias.

Рекомендация : используйте только transclude: trueтогда, когда вы хотите создать директиву для произвольного содержимого.


0

transclude: true означает добавить все элементы, которые определены в вашей директиве, с элементом шаблона вашей директивы.

Если transclude: false, эти элементы не включены в ваш окончательный HTML-код директивы, только шаблон директивы отображается.

transclude: element означает, что ваш шаблон директивы не используется, только элемент, определенный в вашей директиве, отображается как html.

когда вы определяете свою директиву, она должна быть ограничена E, а когда вы добавляете ее на страницу,

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.