Розуміння варіанти включення визначення директиви?


195

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

У документі http://docs.angularjs.org/guide/directive зазначено:

transclude - складіть вміст елемента та зробіть його доступним для директиви. Зазвичай використовується з ngTransclude. Перевага виключення полягає в тому, що функція зв'язування отримує функцію переключення, яка попередньо пов'язана з правильною областю. У типових налаштуваннях віджет створює область ізоляції, але переключення - це не дочірня, а побратима області ізоляту. Це дає можливість віджету мати приватний стан, а переключення прив'язуватися до батьківського (попереднього ізоляції) сфери.

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

Він говорить, transcludeяк правило, використовується з ngTransclude. Але зразок з doc ngTransclude взагалі не використовує ngTranscludeдирективи.

Я хотів би кілька хороших прикладів, які допоможуть мені зрозуміти це. Навіщо нам це потрібно? Що це вирішує? Як ним користуватися?


FYI ... посилання працює принаймні зараз
Сенді

Відповіді:


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? Вам знадобиться щось, що називається переключенням. Концепція досить проста: включіть вміст з одного місця в інше . Тож тепер ваша директива буде виглядати приблизно так:

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 нижче
Тарджей Ромтвейт

20
Дуже-дуже хороша відповідь. Шлях вище норми. У вас є хороші приклади, і ваш "це вміст моєї директиви" зробив його дуже легким для читання у наданій версії. Я не розумію, чому Angular має використовувати складну термінологію та поняття, а потім не включати легкі для розуміння приклади, як ваш. +2
freeall

Хто-небудь знає, чи може переключений вміст посилатися на поля ізоляції директиви? Вище йдеться про те, що виключення - це рідний брат, а не дитина, ізоляторного простору ... тож я припускаю, що це не може, - але цікавилось, чи хтось може підтвердити чи повідомити мені, чи можливо
Саймон Грін

@UladzimirHavenchyk дякую, що вони перенесли відео в інше місце. Я відповідно зафіксував посилання.
odiseo

4
@odiseo, чи не могли б ви написати усі кутові документи простою, зрозумілою англійською мовою, як це! + багато 1-х.
Ден Ходсон

76

Я думаю, що важливо згадати зміни вищезгаданої поведінки в новій версії AngularJS. Я витратив одну годину, намагаючись досягти вищезгаданих результатів за допомогою кутового 1.2.10.

Зміст елемента з ng-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 див. Зміну 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- це атрибут, який виступає в ролі власника місця, всередині якого буде розміщений перекладений вміст.
Будучи Людина

5

З Вікі:

"В інформатиці трансклюзія - це включення частини або всього електронного документа до одного або декількох інших документів шляхом посилання".

Я хотів би додати ще одне використання для переключення, і це те, що він змінює порядок виконання функцій компіляції та зв’язку батьківських та дочірніх директив. Це може бути корисно, коли ви хочете скласти дочірню 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>

my-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 надає вмісту директиви за допомогою цієї опції доступ до сфери дії за межами директиви, а не всередині.

Це проілюстровано в попередньому прикладі. Зауважте, що ми додали функцію посилання в script.js, яка перевизначає ім'я як Джефф. Зазвичай ми очікуємо, що {{name}} буде Джеффом. Однак ми бачимо в цьому прикладі, що прив'язка {{name}} все ще є Тобіасом.

Найкраща практика : використовуйте лише transclude: trueтоді, коли ви хочете створити директиву, яка охоплює довільний вміст.


0

transclude: true mean додати весь елемент, визначений у вашій директиві, до шаблонного елемента вашої директиви.

якщо transclude: false, ці елементи не включені до вашого остаточного html-директиви, надається лише шаблон директиви.

transclude: елемент означає, що ваш шаблон директиви не використовується, лише елемент, визначений у вашій директиві, відображається як 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.