кодесурса
«Угловое

Структурные директивы

script1adsense2code
script1adsense3code

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

Каковы структурные директивы?

Структурные директивы отвечают за макет HTML. Они формируют и изменяют структуру DOM, обычно добавляя, удаляя или манипулируя элементами.

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

Структурные директивы легко распознать. Звездочка (*) предшествует имени атрибута директивы, как в этом примере. (SRC / приложение / app.component.html)

<div *ngIf="hero" class="name">{{hero.name}}</div>

Демонстрация в реальном времени:

См. Структурные директивы Pen по w3resource ( @ w3resource ) в CodePen .


Следует отметить, что без скобок, без скобок просто * ngIf установлен в строку.

В этом руководстве вы узнаете, что звездочка (*) - это удобная нотация, а строка представляет собой микросинтаксис, а не обычное выражение шаблона. Angular desugar это обозначение в размеченный <ng-template>, который окружает хост-элемент и его потомков. Каждая структурная директива делает что-то свое с этим шаблоном.

Существует три наиболее распространенных встроенных структурных директивы, которые включают

  • NgIf
  • NgFor
  • NgSwitch

Вот пример из них в шаблоне: (src / app / app.component.html)

<div *ngIf="hero" class="name">{{hero.name}}</div>
<ul>
  <li *ngFor="let hero of heroes">{{hero.name}}</li>
</ul>
<div [ngSwitch]="hero?.emotion">
  <app-happy-hero    *ngSwitchCase="'happy'"    [hero]="hero"></app-happy-hero>
  <app-sad-hero      *ngSwitchCase="'sad'"      [hero]="hero"></app-sad-hero>
  <app-confused-hero *ngSwitchCase="'confused'" [hero]="hero"></app-confused-hero>
  <app-unknown-hero  *ngSwitchDefault           [hero]="hero"></app-unknown-hero>
</div>

Демонстрация в реальном времени:

Смотрите Примеры пера от w3resource ( @ w3resource ) на CodePen .


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

Директивная орфография

В этом руководстве вы увидите директиву, написанную как в UpperCamelCase, так и в lowerCamelCase. Вы уже видели NgIf и ngIf. Есть причина. NgIf относится к директивному классу; ngIf ссылается на имя атрибута директивы.

Класс директивы пишется в UpperCamelCase (NgIf). Имя атрибута директивы пишется в lowerCamelCase (ngIf). Руководство ссылается на класс директивы, когда говорит о его свойствах и о том, что делает директива. Руководство ссылается на имя атрибута при описании того, как вы применяете директиву к элементу в шаблоне HTML.

Существуют два других типа угловых директив: (1) компоненты и (2) атрибутные директивы.

Директива компонента управляет областью HTML в виде нативного элемента HTML. Технически это директива с шаблоном.

Директива атрибута изменяет внешний вид или поведение элемента, компонента или другой директивы. Например, встроенная директива NgStyle меняет несколько стилей элемента одновременно.

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

NgIf тематическое исследование

NgIf - это самая простая структурная директива и самая простая для понимания. Он принимает логическое выражение и заставляет весь кусок DOM появляться или исчезать.

<p *ngIf="true">
  Expression is true and ngIf is true.
  This paragraph is in the DOM.
</p>
<p *ngIf="false">
  Expression is false and ngIf is false.
  This paragraph is not in the DOM.
</p>

Демонстрация в реальном времени:

См. Pen Ng-if от w3resource ( @ w3resource ) в CodePen .


Директива ngIf не скрывает элементы с помощью CSS. Он добавляет и удаляет их физически из DOM. Подтвердите этот факт, используя инструменты разработчика браузера для проверки DOM.


Верхний абзац находится в DOM. Внизу, заброшенный абзац нет; на его месте комментарий о «привязках».

Когда условие ложно, NgIf удаляет свой хост-элемент из DOM, отсоединяет его от событий DOM (вложений, которые он сделал), отсоединяет компонент от обнаружения угловых изменений и уничтожает его. Компонент и узлы DOM могут быть собраны мусором и освободить память.

Зачем удалять, а не скрывать ?

Директива может скрыть нежелательный абзац, установив для его стиля отображения значение none.

<p [style.display]="'block'">
  Expression sets display to "block".
  This paragraph is visible.
</p>
<p [style.display]="'none'">
  Expression sets display to "none".
  This paragraph is hidden but still in the DOM.
</p>

Демонстрация в реальном времени:

См. Pen display-none от w3resource ( @ w3resource ) в CodePen .


Пока невидимый, элемент остается в DOM


Разница между сокрытием и удалением не имеет значения для простого абзаца. Имеет значение, когда элемент хоста подключен к ресурсоемкому компоненту. Поведение такого компонента продолжается даже тогда, когда оно скрыто. Компонент остается подключенным к своему элементу DOM. Он продолжает слушать события. Angular продолжает проверять изменения, которые могут повлиять на привязки данных. Что бы ни делал компонент, он продолжает делать.

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

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

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

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

Звездочка (*) префикс

Конечно, вы заметили префикс asterisk (*) к имени директивы и поинтересовались, зачем это нужно и для чего оно нужно.

Вот * ngЕсли отображается имя героя, если герой существует.

<div *ngIf="hero" class="name">{{hero.name}}</div>

Демонстрация в реальном времени:

См. Pen xNZExL от w3resource ( @ w3resource ) в CodePen .


Звездочка - это «синтаксический сахар» для чего-то более сложного. Внутренне Angular переводит атрибут * ngIf в элемент <ng-template>, обернутый вокруг элемента host, вот так.

<ng-template [ngIf]="hero">
  <div class="name">{{hero.name}}</div>
</ng-template>

Демонстрация в реальном времени:

См. Pen ng-if от w3resource ( @ w3resource ) в CodePen .


  • Директива * ngIf перемещена в элемент <ng-template>, где она стала привязкой свойства, [ngIf].
  • Остальная часть <div>, включая атрибут class, перемещена внутри элемента <ng-template>.

Первая форма фактически не отображается, в DOM попадает только готовый продукт.

«ngIf

Angular использовал содержимое <ng-template> во время его фактического рендеринга и заменил <ng-template> диагностическим комментарием.

Директивы NgFor и NgSwitch ... следуют одному и тому же шаблону. Внутри * ngFor

Angular аналогичным образом преобразует * ngFor из синтаксиса звездочки (*) в элемент <ng-template>.

Вот полнофункциональное приложение NgFor, написанное в двух направлениях:

<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
  <div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>

Демонстрация в реальном времени:

Смотрите Pen ng-for от w3resource ( @ w3resource ) в CodePen .


Это явно сложнее, чем ngIf, и это правильно. Директива NgFor имеет больше возможностей, как обязательных, так и необязательных, чем NgIf, показанный в этом руководстве. Как минимум, для NgFor необходимы циклическая переменная (пусть герой) и список (герои).

Вы включаете эти функции в строке, назначенной ngFor, которую вы пишете в микросинтаксисе Angular.

Все, что находится за пределами строки ngFor, остается с главным элементом (<div>), так как он перемещается внутри <ng-template>. В этом примере [ngClass] = "odd" остается на </ div>

Microsyntax

Микросинтаксис Angular позволяет вам сконфигурировать директиву в виде удобной компактной строки. Синтаксический анализатор микросинтаксиса преобразует эту строку в атрибуты в <ng-template>:

  • Ключевое слово let объявляет входную переменную шаблона, на которую вы ссылаетесь в шаблоне. Входными переменными в этом примере являются hero, i и odd. Парсер переводит let hero, let i и let odd в переменные с именами let-hero, let-i и let-odd.
  • Синтаксический синтаксический анализатор принимает и trackBy, присваивает им титры (of -> Of, trackBy -> TrackBy) и префиксирует их именем атрибута директивы (ngFor), получая имена ngForOf и ngForTrackBy. Это имена двух входных свойств NgFor. Вот как директива узнает, что список - это герои, а функция отслеживания - trackById.
  • Когда директива NgFor проходит по списку, она устанавливает и сбрасывает свойства своего собственного объекта контекста. Эти свойства включают index и odd и специальное свойство с именем $ implicit.
  • Переменные let-i и let-odd были определены как let i = index и let odd = odd. Angular устанавливает для них текущее значение индекса контекста и нечетные свойства.
  • Свойство context для let-hero не указано. Предполагаемый источник неявный. Angular устанавливает значение let-hero в значении $ implicit свойства контекста, которое NgFor инициализировал с hero для текущей итерации.
  • Руководство по API описывает дополнительные свойства директивы NgFor и свойства контекста.
  • NgFor реализуется директивой NgForOf.

Эти механизмы микросинтаксиса доступны вам, когда вы пишете свои собственные структурные директивы.

Входная переменная шаблона

Входная переменная шаблона - это переменная, на значение которой вы можете ссылаться в пределах одного экземпляра шаблона. В этом примере есть несколько таких переменных: hero, i и odd. Всем предшествует ключевое слово let.

Входная переменная шаблона - это не то же самое, что ссылочная переменная шаблона, ни семантически, ни синтаксически.

Вы объявляете входную переменную шаблона, используя ключевое слово let (let hero). Область действия переменной ограничена одним экземпляром повторяющегося шаблона. Вы можете снова использовать то же имя переменной в определении других структурных директив.

Вы объявляете переменную ссылки на шаблон, добавляя к имени переменной префикс # (#var). Ссылочная переменная ссылается на связанный с ней элемент, компонент или директиву. К нему можно получить доступ в любом месте всего шаблона.

Имена входных и справочных переменных шаблонов имеют свои собственные пространства имен. Герой в let hero никогда не будет такой же переменной, как герой, объявленный как #hero.

Одна структурная директива на элемент хоста

Когда-нибудь вы захотите повторить блок HTML, но только когда определенное условие выполнено. Вы попытаетесь поместить и * ngFor, и * ngIf в один и тот же элемент хоста. Angular не позволит вам. Вы можете применять только одну структурную директиву к элементу.

Причина простота. Структурные директивы могут делать сложные вещи с элементом host и его потомками. Когда две директивы претендуют на один и тот же хост-элемент, какая из них имеет приоритет? Что должно идти первым, NgIf или NgFor? Может ли NgIf отменить эффект NgFor? Если так (и кажется, что так и должно быть), как Angular должен обобщать возможность отмены для других структурных директив?

На эти вопросы нет простых ответов. Запрещение нескольких структурных директив делает их спорными. Для этого варианта использования есть простое решение: поместите * ngIf в элемент контейнера, который обернет элемент * ngFor. Один или оба элемента могут быть контейнером ng, поэтому вам не нужно вводить дополнительные уровни HTML

Внутри директивы NgSwitch

Angular NgSwitch - это набор взаимодействующих директив: NgSwitch, NgSwitchCase и NgSwitchDefault.

Вот пример.

<div [ngSwitch]="hero?.emotion">
  <app-happy-hero    *ngSwitchCase="'happy'"    [hero]="hero"></app-happy-hero>
  <app-sad-hero      *ngSwitchCase="'sad'"      [hero]="hero"></app-sad-hero>
  <app-confused-hero *ngSwitchCase="'confused'" [hero]="hero"></app-confused-hero>
  <app-unknown-hero  *ngSwitchDefault           [hero]="hero"></app-unknown-hero>
</div>

Демонстрация в реальном времени:

См. Nn -переключатель Pen by w3resource ( @ w3resource ) в CodePen .


Значение переключателя, назначенное NgSwitch (hero.emotion), определяет, какие (если есть) варианты переключений отображаются.

Сам NgSwitch не является структурной директивой. Это директива атрибута, которая управляет поведением двух других директив switch. Вот почему вы пишете [ngSwitch], а не * ngSwitch.

NgSwitchCase и NgSwitchDefault являются структурными директивами. Вы присоединяете их к элементам, используя префиксную звездочку (*). NgSwitchCase отображает свой хост-элемент, когда его значение соответствует значению переключателя. NgSwitchDefault отображает свой хост-элемент, если ни один из родственных NgSwitchCase не соответствует значению переключателя.

Элемент, к которому вы применяете директиву, является его элементом host. <Happy-hero> - это элемент хоста для happy * ngSwitchCase. <Unknown-hero> является хост-элементом для * ngSwitchDefault.

Как и в случае с другими структурными директивами, NgSwitchCase и NgSwitchDefault могут быть преобразованы в форму элемента <ng-template>.

<div [ngSwitch]="hero?.emotion">
  <ng-template [ngSwitchCase]="'happy'">
    <app-happy-hero [hero]="hero"></app-happy-hero>
  </ng-template>
  <ng-template [ngSwitchCase]="'sad'">
    <app-sad-hero [hero]="hero"></app-sad-hero>
  </ng-template>
  <ng-template [ngSwitchCase]="'confused'">
    <app-confused-hero [hero]="hero"></app-confused-hero>
  </ng-template >
  <ng-template ngSwitchDefault>
    <app-unknown-hero [hero]="hero"></app-unknown-hero>
  </ng-template>
</div>

Демонстрация в реальном времени:

Смотрите Pen ng-switch-templete от w3resource ( @ w3resource ) в CodePen .


Предпочитаю звездочку (*) синтаксис.

Синтаксис звездочки (*) более понятен, чем десагаред. Используйте <ng-container>, когда нет единого элемента для размещения директивы.

Хотя редко есть веская причина для применения структурной директивы в атрибуте шаблона или форме элемента, все же важно знать, что Angular создает <ng-template>, и понимать, как он работает. Вы будете ссылаться на <ng-template>, когда будете писать свою собственную структурную директиву.

<Ng-template>

<Ng-template> - это угловой элемент для рендеринга HTML. Он никогда не отображается напрямую. Фактически, перед рендерингом представления Angular заменяет <ng-template> и его содержимое комментарием.

Если структурной директивы нет и вы просто заключаете некоторые элементы в <ng-template>, эти элементы исчезают. Это судьба середины "Бедро!" в фразе «Бедро! Бедро! Ура!».

<p>Hip!</p>
<ng-template>
  <p>Hip!</p>
</ng-template>
<p>Hooray!</p>

Демонстрация в реальном времени:

См. Pen YbwGxd от w3resource ( @ w3resource ) на CodePen .


Angular стирает середину «Hip!», Оставляя приветствие чуть менее восторженным.

«Угловое

Структурная директива заставляет работать <ng-template>, как вы увидите, когда будете писать свою собственную структурную директиву.

Сгруппируйте одноуровневые элементы с помощью <ng-container>

Часто существует корневой элемент, который может и должен содержать структурную директиву. Элемент списка (<li>) является типичным хост-элементом повторителя NgFor.

src / app / app.component.html (ngfor-li)

<li *ngFor="let hero of heroes">{{hero.name}}</li>

Если элемент host отсутствует, вы обычно можете обернуть содержимое в собственный элемент контейнера HTML, такой как <div>, и прикрепить директиву к этой оболочке.

<div *ngIf="hero" class="name">{{hero.name}}</div>

Введение другого элемента контейнера - обычно <span> или <div> - для группировки элементов под одним корнем, как правило, безвредно. Обычно ... но не всегда.

Элемент группировки может нарушить внешний вид шаблона, поскольку стили CSS не ожидают и не приспосабливают новый макет. За Например, предположим, что у вас есть следующий макет абзаца.

<p>
  I turned the corner
  <span *ngIf="hero">
    and saw {{hero.name}}. I waved
  </span>
  and continued on my way.
</p>

Демонстрация в реальном времени:

Смотрите Pen ng-if-span от w3resource ( @ w3resource ) в CodePen .


У вас также есть правило стиля CSS, которое применяется к <span> в абзаце <p>.

p span { color: red; font-size: 70%; }

Построенный абзац выглядит странно.

Стиль p span, предназначенный для использования в других местах, был непреднамеренно применен здесь.

Другая проблема: некоторые элементы HTML требуют, чтобы все непосредственные потомки были определенного типа. Например, элементу <select> требуются дочерние элементы <option>. Вы не можете обернуть параметры в условный <div> или <span>.

Когда вы попробуете это,

<div>
  Pick your favorite hero
  (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
</div>
<select [(ngModel)]="hero">
  <span *ngFor="let h of heroes">
    <span *ngIf="showSad || h.emotion !=='sad'">
      <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
    </span>
  </span>
</select>

Демонстрация в реальном времени:

См. Pen dEGpdQ от w3resource ( @ w3resource ) в CodePen .


«пусто

Браузер не будет отображать <option> внутри <span>.

<ng-container> на помощь

Angular <ng-container> - это группирующий элемент, который не мешает стилям или макету, поскольку Angular не помещает его в DOM.

Вот снова условный абзац, на этот раз с использованием <ng-container>.

<p>
  I turned the corner
  <ng-container *ngIf="hero">
    and saw {{hero.name}}. I waved
  </ng-container>
  and continued on my way.
</p>

Демонстрация в реальном времени:

См. Pen MdKjXo от w3resource ( @ w3resource ) на CodePen .


Это делает правильно.

«условная

Теперь условно исключите select <option> с помощью <ng-container>.

<div>
  Pick your favorite hero
  (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
</div>
<select [(ngModel)]="hero">
  <ng-container *ngFor="let h of heroes">
    <ng-container *ngIf="showSad || h.emotion !=='sad'">
      <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
    </ng-container>
  </ng-container>
</select>

Демонстрация в реальном времени:

См. Pen QRyMVK от w3resource ( @ w3resource ) в CodePen .


Раскрывающийся список работает правильно

«условно

Примечание. Помните, что директива ngModel определена как часть Angular FormsModule, и вам необходимо включить FormsModule в раздел import: [...] метаданных модуля Angular, в котором вы хотите его использовать.

<Ng-container> - это синтаксический элемент, распознаваемый анализатором Angular. Это не директива, компонент, класс или интерфейс. Это больше похоже на фигурные скобки в JavaScript-блоке if:

if (someCondition) {
  statement1;
  statement2;
  statement3;
}

Демонстрация в реальном времени:

См. Pen oRbeVm от w3resource ( @ w3resource ) в CodePen .


Без этих фигурных скобок JavaScript будет выполнять первый оператор только тогда, когда вы намереваетесь выполнить их все как один блок. <Ng-container> удовлетворяет аналогичную потребность в шаблонах Angular.

Написать структурную директиву

В этом разделе вы пишете структурную директиву UnlessDirective, которая противоположна NgIf. NgIf отображает содержимое шаблона, когда условие выполняется. UnlessDirective отображает содержимое, когда условие ложно.

src / app / app.component.html (appUnless-1)
<p *appUnless="condition">Show this sentence unless the condition is true.</p>

Демонстрация в реальном времени:

См. Pen wbMqbG от w3resource ( @ w3resource ) в CodePen .


Создание директивы похоже на создание компонента.

  • Импортируйте Директивный декоратор (вместо Компонентного декоратора).
  • Импортируйте символы Input, TemplateRef и ViewContainerRef; они понадобятся вам для любой структурной директивы.
  • Примените декоратор к классу директивы.
  • Установите селектор атрибута CSS, который идентифицирует директиву при применении к элементу в шаблоне.

Вот как вы можете начать:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
}

Демонстрация в реальном времени:

См. Pen vwLJqo от w3resource ( @ w3resource ) на CodePen .


Селектором директивы обычно является имя атрибута директивы в квадратных скобках, [appUnless]. Скобки определяют селектор атрибута CSS.

Имя атрибута директивы должно быть записано в lowerCamelCase и начинаться с префикса. Не используйте нг. Этот префикс принадлежит Angular. Выберите что-нибудь короткое, что подходит вам или вашей компании. В этом примере префикс app.

Имя класса директивы оканчивается на Директиву в соответствии с руководством по стилю. Собственные директивы Angular этого не делают.

TemplateRef и ViewContainerRef

Такая простая структурная директива, как эта, создает внедренное представление из сгенерированного Angular <ng-template> и вставляет это представление в контейнер представления, смежный с исходным хост-элементом директивы <p>.

Вы получите содержимое <ng-template> с TemplateRef и получите доступ к контейнеру представления через aViewContainerRef.

Вы вводите оба в конструктор директивы как частные переменные класса.

copyconstructor(
  private templateRef: TemplateRef<any>,
  private viewContainer: ViewContainerRef) { }

Демонстрация в реальном времени:

См. Pen xNZXKy от w3resource ( @ w3resource ) в CodePen .


Свойство appUnless

Потребитель директивы ожидает связать условие true / false с [appUnless]. Это означает, что директиве нужно свойство appUnless, украшенное @Input

@Input() set appUnless(condition: boolean) {
  if (!condition && !this.hasView) {
    this.viewContainer.createEmbeddedView(this.templateRef);
    this.hasView = true;
  } else if (condition && this.hasView) {
    this.viewContainer.clear();
    this.hasView = false;
  }
}

Демонстрация в реальном времени:

Смотрите перо wbMrBz от w3resource ( @ w3resource ) на CodePen .


Angular устанавливает свойство appUnless всякий раз, когда изменяется значение условия. Поскольку свойство appUnless работает, ему нужен установщик.

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

Никто не читает свойство appUnless, поэтому для него не нужен геттер.

Законченный код директивы выглядит так:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
/**
 * Add the template content to the DOM unless the condition is true.
 */
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
  private hasView = false;
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef) { }
  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}

Демонстрация в реальном времени:

См. Pen ardLOR от w3resource ( @ w3resource ) в CodePen .


Добавьте эту директиву в массив объявлений AppModule.

Затем создайте HTML, чтобы попробовать.

<p *appUnless="condition" class="unless a">
  (A) This paragraph is displayed because the condition is false.
</p>
<p *appUnless="!condition" class="unless b">
  (B) Although the condition is true,
  this paragraph is displayed because appUnless is set to false.
</p>

Демонстрация в реальном времени:

См. Pen WBrZQp от w3resource ( @ w3resource ) на CodePen .


Когда условие ложное, появляется верхний (A) абзац, а нижний (B) абзац исчезает. Когда условие верно, верхний абзац (A) удаляется, а нижний (B) абзац появляется.

«угловая

Предыдущая: Использование опубликованных библиотек
Далее: Отображение данных

Новый контент: Composer: менеджер зависимостей для PHP , R программирования


script1adsense4code
script1adsense5code
disqus2code
script1adsense6code
script1adsense7code
script1adsense8code
buysellads2code