
Куративная коллекция полезных угловых фрагментов, которые вы можете понять за 30 секунд или меньше.
Начальные фрагменты
Промежуточные фрагменты
Усовершенствованные фрагменты
Перечисления великолепны, но они не видны в угловых шаблонах по умолчанию. С этим маленьким трюком вы можете сделать их доступными.
enum Animals {
DOG ,
CAT ,
DOLPHIN
}
@ Component ( {
...
} )
export class AppComponent {
animalsEnum : typeof Animals = Animals ;
}
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: перечисления шаблонов
Проверьте угловой шпаргалка или (альтернативная версия), содержащая много полезной информации, конденсированной в одном месте.
Также угловой контрольный список содержит курированный список общих ошибок, допущенных при разработке угловых приложений.
https://malcoded.com/angular-cheat-sheet/,https://angular.io/guide/cheatsheet,https://angular.io/guide/styleguide
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: шпаргалка
Отлаживать состояние компонента в консоли браузера, работая:
ng . probe ( $0 ) . componentInstance
$0- это узел DOM, который в настоящее время выбран в Dev Tools ($1за предыдущий и так далее).
С двигателем рендеринга плюща:
ng . getComponent ( $0 ) https://blog.angularindepth.com/everything-you-need-to-cons-about-debugging-angular-applications-d308ed8a51b4
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: советы хорошего для знания
Если вы используете значение ViewEncapsulation , которое отличается от дефолта, может быть пугающим устанавливать значение вручную для каждого компонента.
К счастью, вы можете настроить его по всему миру при начальной загрузке вашего приложения:
platformBrowserDynamic ( ) . bootstrapModule ( AppModule , [
{
// NOTE: Use ViewEncapsulation.None only if you know what you're doing.
defaultEncapsulation : ViewEncapsulation . None
}
] ) ;
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: стиль конфигурации
Чтобы действовать на Swipes, Pans и Pinhces, а также на другие мобильные жесты, вы можете использовать hammerjs с декоратором HostListener или привязку события,
npm install hammerjs@ HostListener ( 'swiperight' )
public swiperight ( ) : void {
// Run code when a user swipes to the right
} Вот образцы о том, как использовать все привязки hammerjs событий, вы также можете использовать эти события с помощью HostListener :
<!-- pan events -->
< div (pan) =" logEvent($event) " > </ div >
< div (panstart) =" logEvent($event) " > </ div >
< div (panmove) =" logEvent($event) " > </ div >
< div (panend) =" logEvent($event) " > </ div >
< div (pancancel) =" logEvent($event) " > </ div >
< div (panleft) =" logEvent($event) " > </ div >
< div (panright) =" logEvent($event) " > </ div >
< div (panup) =" logEvent($event) " > </ div >
< div (pandown) =" logEvent($event) " > </ div >
<!-- pinch events -->
< div (pinch) =" logEvent($event) " > </ div >
< div (pinchstart) =" logEvent($event) " > </ div >
< div (pinchmove) =" logEvent($event) " > </ div >
< div (pinchend) =" logEvent($event) " > </ div >
< div (pinchcancel) =" logEvent($event) " > </ div >
< div (pinchin) =" logEvent($event) " > </ div >
< div (pinchout) =" logEvent($event) " > </ div >
<!-- press events -->
< div (press) =" logEvent($event) " > </ div >
< div (pressup) =" logEvent($event) " > </ div >
<!-- rotate events -->
< div (rotate) =" logEvent($event) " > </ div >
< div (rotatestart) =" logEvent($event) " > </ div >
< div (rotatemove) =" logEvent($event) " > </ div >
< div (rotateend) =" logEvent($event) " > </ div >
< div (rotatecancel) =" logEvent($event) " > </ div >
<!-- swipe events -->
< div (swipe) =" logEvent($event) " > </ div >
< div (swipeleft) =" logEvent($event) " > </ div >
< div (swiperight) =" logEvent($event) " > </ div >
< div (swipeup) =" logEvent($event) " > </ div >
< div (swipedown) =" logEvent($event) " > </ div >
<!-- tap event -->
< div (tap) =" logEvent($event) " > </ div > https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/hammer_gestures.ts,http://hammerjs.github.io/api/#hammer.manager,https://angular.io/api/platform-browser/HammerGestureConfig
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Жесты компонентов хорошего знания
Вы можете создать собственный вспомогательный компонент и использовать его вместо *ngIf .
@ Component ( {
selector : 'loader' ,
template : `
<ng-content *ngIf="!loading else showLoader"></ng-content>
<ng-template #showLoader>? Wait 10 seconds!</ng-template>
`
} )
class LoaderComponent {
@ Input ( ) loading : boolean ;
}Для примера использования:
< loader [loading] =" isLoading " > ? ? ? </ loader >Обратите внимание, что контент будет с нетерпением ждать оценки, например, в фрагменте ниже
destroy-the-worldбудет создан еще до начала загрузки:
< loader [loading] =" isLoading " > < destroy-the-world > </ destroy-the-world > </ loader > https://medium
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Советы хороших для знания шаблонов компонентов
С ng-content вы можете передать любые элементы компоненту. Это упрощает создание многоразовых компонентов.
@ Component ( {
selector : 'wrapper' ,
template : `
<div class="wrapper">
<ng-content></ng-content>
</div>
` ,
} )
export class Wrapper { } < wrapper >
< h1 > Hello World! </ h1 >
</ wrapper > https://medium.com/p/96a29d70d11b
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Компоненты советов хорошего для знания
*ngIf также поддерживает Заявление else .
< div *ngIf =" isLoading; else notLoading " > loading... </ div >
< ng-template #notLoading > not loading </ ng-template >
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: ngif шаблоны
Перейдите с матричными параметрами:
Маршрутизатор перейдет к /first;name=foo/details
< a [routerLink] =" ['/', 'first', {name: 'foo'}, 'details'] " >
link with params
</ a > https://stackblitz.com/edit/angular-xvy5pd
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: маршрутизация
В некоторых случаях свойства @Input и @Output могут быть названы иначе, чем фактические входы и выходы.
< div
pagination
paginationShowFirst =" true "
(paginationPageChanged) =" onPageChanged($event) " >
</ div > @ Directive ( { selector : '[pagination]' } )
class PaginationComponent {
@ Input ( 'paginationShowFirst' )
showFirst : boolean = true ;
@ Output ( 'paginationPageChanged' )
pageChanged = new EventEmitter ( ) ;
}ПРИМЕЧАНИЕ. Используйте это с умом, см. Syleguide Рекомендуется
https://angular.io/guide/styleguide#style-05-13
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: шаблоны компонентов
Безопасная навигационная оператор помогает в предотвращении исключений из нулевых ссылок в выражениях шаблонов компонентов. Он возвращает значение свойства объекта, если он существует или иначе нулевой.
< p > I will work even if student is null or undefined: {{student?.name}} </ p >{{a?.b?.c}} Внизу будут составлены.
(_co.a == null)? null: ((_co.a.b == null)? null: _co.a.b.c));Угловой/угловой#791
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Советы по обработке объекта
Чтобы избежать дорогостоящих операций, мы можем помочь угловым отслеживать, какие элементы добавлены или удалили, IE настроить алгоритм отслеживания по умолчанию, предоставив опцию Trackby для NGFOROF.
Таким образом, вы можете предоставить свою пользовательскую функцию трека, которая вернет уникальный идентификатор для каждого итерационного элемента. Например, некоторое значение ключа элемента. Если это значение ключа соответствует предыдущему, то Angular не обнаруживает изменения.
Trackby принимает функцию, которая имеет INDEX и ARG ARGS.
@ Component ( {
selector : 'my-app' ,
template : `
<ul>
<li *ngFor="let item of items; trackBy: trackByFn">{{item.id}}</li>
</ul>
`
} )
export class AppComponent {
trackByFn ( index , item ) {
return item . id ;
}
}Если дается трекби, угловые треки изменяются по возвращению значения функции.
Теперь, когда вы измените коллекцию, Angular может отслеживать, какие элементы были добавлены или удалены в соответствии с уникальным идентификатором и создают/разрушают только измененные элементы.
https://angular.io/api/common/ngforof, https://angular.io/api/core/trackbyfunction
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: хорошие советы по знанию производительность компонентов
Под капотом угловой компиляции структурные директивы в элементы NG-Template, например:
<!-- This -->
< div *ngFor =" let item of [1,2,3] " >
<!-- Get expanded into this -->
< ng-template ngFor [ngForOf] =" [1,2,3] " let-item =" $implicit " > </ ng-template >Значение, передаваемое в Директиву, написано с использованием Microsyntax. Вы можете узнать об этом в документах.
Также ознакомьтесь с интерактивным инструментом, который показывает расширение Алекси Зуэв.
https://angular.io/guide/structural-directives#microsyntax,https://alexzuza.github.io/ng-structural-directive-expander/,https://angular.io/guide/structural-directiveside-ngfor
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: совет по структурной директиве Microsyntax
Иногда нам нужно работать с каждым отдельным управлением - это форма. Вот как это можно сделать:
function flattenControls ( form : AbstractControl ) : AbstractControl [ ] {
let extracted : AbstractControl [ ] = [ form ] ;
if ( form instanceof FormArray || form instanceof FormGroup ) {
const children = Object . values ( form . controls ) . map ( flattenControls ) ;
extracted = extracted . concat ( ... children ) ;
}
return extracted ;
}Для примеров Использование:
// returns all dirty abstract controls
flattenControls ( form ) . filter ( ( control ) => control . dirty ) ;
// mark all controls as touched
flattenControls ( form ) . forEach ( ( control ) =>
control . markAsTouched ( { onlySelf : true } ) ) ; https://angular.io/guide/reactive-forms
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Реактивные формы Советы хорошо знать
В шаблоне действительно легко добавить сочетания клавиатуры:
< textarea (keydown.ctrl.enter) =" doSomething() " > </ textarea > < input (keydown.enter) =" ... " >
< input (keydown.a) =" ... " >
< input (keydown.esc) =" ... " >
< input (keydown.shift.esc) =" ... " >
< input (keydown.control) =" ... " >
< input (keydown.alt) =" ... " >
< input (keydown.meta) =" ... " >
< input (keydown.9) =" ... " >
< input (keydown.tab) =" ... " >
< input (keydown.backspace) =" ... " >
< input (keydown.arrowup) =" ... " >
< input (keydown.shift.arrowdown) =" ... " >
< input (keydown.shift.control.z) =" ... " >
< input (keydown.f4) =" ... " > https://alligator.io/angular/binding-keyup-keydown-events
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Советы хороши для знания
Каждый визуализированный угловой компонент обернут в хост -элемент (который такой же, как селектор компонента).
Можно связать свойства и атрибуты элемента хоста с использованием декораторов @hostbinding, например,
import { Component , HostBinding } from '@angular/core' ;
@ Component ( {
selector : 'my-app' ,
template : `
<div>Use the input below to select host background-color:</div>
<input type="color" [(ngModel)]="color">
` ,
styles : [
`:host { display: block; height: 100px; }`
]
} )
export class AppComponent {
@ HostBinding ( 'style.background' ) color = '#ff9900' ;
}
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: компоненты
Как правило, мы получаем один экземпляр службы за все приложение. Также возможно создать экземпляр службы на компонент или директиву.
@ Component ( {
selector : 'provide' ,
template : '<ng-content></ng-content>' ,
providers : [ Service ]
} )
export class ProvideComponent { } @ Directive ( {
selector : '[provide]' ,
providers : [ Service ]
} )
export class ProvideDirective { } https://angular.io/guide/hierarchical-tependency-incement#component level Injectors, https://stackblitz.com/edit/angular-cdk-happy-animals
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Советы компоненты Инъекция зависимости
Можно добавить глобальных слушателей событий в ваши компоненты/директивы с HostListener . Angular позаботится о отказе, когда ваша директива будет уничтожена.
@ Directive ( {
selector : '[rightClicker]'
} )
export class ShortcutsDirective {
@ HostListener ( 'window:keydown.ArrowRight' )
doImportantThings ( ) {
console . log ( 'You pressed right' ) ;
}
}Вы можете иметь несколько привязков:
@ HostListener ( 'window:keydown.ArrowRight' )
@ HostListener ( 'window:keydown.PageDown' )
next ( ) {
console . log ( 'Next' )
}Вы также можете перенести параметры:
@ HostListener ( 'window:keydown.ArrowRight' , '$event.target' )
next ( target ) {
console . log ( 'Pressed right on this element: ' + target )
}
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: компоненты событий
Иногда вам нужно получить доступ к глобальному document .
Чтобы упростить тестирование на единицу, Angular обеспечивает его через инъекцию зависимости:
import { DOCUMENT } from '@angular/common' ;
import { Inject } from '@angular/core' ;
@ Component ( {
selector : 'my-app' ,
template : `<h1>Edit me </h1>`
} )
export class AppComponent {
constructor ( @ Inject ( DOCUMENT ) private document : Document ) {
// Word with document.location, or other things here....
}
} https://angular.io/api/common/document
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: инъекция зависимости
Вот способ уведомить пользователя о том, что существуют поля с неправенными значениями.
markFieldsAsTouched Форма или формара или формара в качестве аргумента.
function markFieldsAsTouched ( form : AbstractControl ) : void {
form . markAsTouched ( { onlySelf : true } ) ;
if ( form instanceof FormArray || form instanceof FormGroup ) {
Object . values ( form . controls ) . forEach ( markFieldsAsTouched ) ;
}
}Очень полезно проверить более общий метод, доступа к всем вложенным элементам управления формой со стороны Thekiba для работы с элементами управления.
https://angular.io/guide/reactive-forms
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Реактивные формы Советы по проверке
EventEmitters используемые для @Output , просто наблюдаются с методом Emit.
Это означает, что вместо этого вы можете просто использовать Observable экземпляр, например, мы можем подключить изменение значения FormControl напрямую:
readonly checkbox = new FormControl ( ) ;
@ Output ( ) readonly change = this . checkbox . valueChanges ;
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: выходы на совет
Можно взять шаблон в качестве @Input для компонента для настройки рендеринга
@ Component ( {
template : `
<nav>
<ng-container *ngTemplateOutlet="template"></ng-container>
</nav>
` ,
} )
export class SiteMenuComponent {
@ Input ( ) template : TemplateRef < any > ;
} < site-menu [template] =" menu1 " > </ site-menu >
< ng-template #menu1 >
< div > < a href =" # " > item1 </ a > </ div >
< div > < a href =" # " > item2 </ a > </ div >
</ ng-template >Примечание:
ng-contentдолжен использоваться для большинства случаев, и это проще и декларативно. Используйте этот подход, только если вам нужна дополнительная гибкость, которая не может быть достигнута с помощью NG-контента.
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: шаблон
По умолчанию угловые полоски все пробелы в шаблонах для сохранения байтов. Вообще это безопасно.
Для редких случаев, когда вам нужно сохранить пространства, вы можете использовать специальный атрибут ngPreserveWhitespaces :
< div ngPreserveWhitespaces >
(___()'`;
/, /`
jgs \"--\
</ div >Вы также можете использовать опцию repervewhitpaces на компоненте.
https://twitter.com/mgechev/status/1108913389277839360
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Совет
Хотя лучший способ повторного использования вашего кода - создание компонента, также можно сделать в шаблоне.
Для этого вы можете использовать ng-template вместе с директивой *ngTemplateOutlet .
< p >
< ng-container *ngTemplateOutlet =" fancyGreeting " > </ ng-container >
</ p >
< button >
< ng-container *ngTemplateOutlet =" fancyGreeting " > </ ng-container >
</ button >
< ng-template #fancyGreeting >
Hello < b > {{name}}! </ b >
</ ng-template > https://angular.io/api/common/ngtemplateoutlet, https://angular.io/guide/structural-directives#the-ng-template
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: шаблоны
Если вам нужна пользовательская pipe , перед тем, как создать одну, рассмотрите возможность проверки пакета Pipes NGX, в котором 70+ уже внедрены пользовательские трубы.
Вот несколько примеров:
< p > {{ date | timeAgo }} </ p >
<!-- Output: "last week" -->
< p > {{ 'foo bar' | ucfirst }} </ p >
<!-- Output: "Foo bar" -->
< p > 3 {{ 'Painting' | makePluralString: 3 }} </ p >
<!-- Output: "3 Paintings" -->
< p > {{ [1, 2, 3, 1, 2, 3] | max }} </ p >
<!-- Output: "3" --> https://github.com/danrevah/ngx-pipes
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: библиотека Tip Pipes
Вы можете использовать расширенные привязки свойств для установки конкретных значений стиля на основе значений свойств компонентов:
< p [style.background-color] =" 'green' " >
I am in green background
</ p >
< p [style.font-size.px] =" isImportant ? '30' : '16' " >
May be important text.
</ p > <!-- Width in pixels -->
< div [style.width.px] =" pxWidth " > </ div >
<!-- Font size in percentage relative to the parent -->
< div [style.font-size.%] =" percentageSize " > ... </ div >
<!-- Height relative to the viewport height -->
< div [style.height.vh] =" vwHeight " > </ div >
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: стили
Подобно тому, как вы можете двустороннее связывать [(ngModel)] вы можете двустороннее свое свойство привязать на компоненте, например [(value)] . Для его использования соответствующее именование ввода/вывода:
@ Component ( {
selector : 'super-input' ,
template : `...` ,
} )
export class AppComponent {
@ Input ( ) value : string ;
@ Output ( ) valueChange = new EventEmitter < string > ( ) ;
}Тогда вы можете использовать его как:
< super-input [(value)] =" value " > </ super-input >
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: привязка совет
Можно выполнить асинхронную задачу, прежде чем приложение начнется, предоставив функцию, возвращающую обещание, используя токен APP_INITIALIZER .
@ NgModule ( {
providers : [
{
provide : APP_INITIALIZER ,
useValue : functionReturningPromise
multi : true
} ,
} )
export class AppModule { }
https://hackernoon.com/hook-into-angular initialization-process-add41a6b7e,https://angular.io/api/core/app_initializer
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Совет
В целях тестирования вы можете захотеть ввести объект window.location в свой компонент. Вы можете достичь этого с помощью индивидуального механизма InjectionToken обеспеченного угловым.
export const LOCATION_TOKEN = new InjectionToken < Location > ( 'Window location object' ) ;
@ NgModule ( {
providers : [
{ provide : LOCATION_TOKEN , useValue : window . location }
]
} )
export class SharedModule { }
//...
@ Component ( {
} )
export class AppComponent {
constructor (
@ Inject ( LOCATION_TOKEN ) public location : Location
) { }
} https://itnext.io/testing-browser-window-location-in-angular-application-e4e8388508ff,https://angular.io/guide/dependency-incement
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: тестирование инъекции зависимости
Можно использовать @ViewChild (также @ViewChildren и @ContentChild/Children ) для запроса компонентов различных типов с использованием инъекции зависимости.
В приведенном ниже примере мы можем использовать @ViewChildren(Base) , чтобы получить экземпляры Foo и Bar .
abstract class Base { }
@ Component ( {
selector : 'foo' ,
providers : [ { provide : Base , useExisting : Foo } ]
} )
class Foo extends Base { }
@ Component ( {
selector : 'bar' ,
providers : [ { provide : Base , useExisting : Bar } ]
} )
class Bar extends Base { }
// Now we can require both types of components using Base.
@ Component ( { template : `<foo></foo><bar></bar>` } )
class AppComponent {
@ ViewChildren ( Base ) components : QueryList < Base > ;
} https://www.youtube.com/watch?v=PRRGO6F0CJS
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Компоненты с хорошим знакомым
Angular позволяет нам контролировать способ обработки предварительной загрузки модуля.
Есть 2 стратегии, предоставленные @angular/router : PreloadAllModules и NoPreloading . Последний включен по умолчанию, только предварительно загружает ленивые модули по требованию.
Мы можем переопределить это поведение, предоставив пользовательскую стратегию предварительной загрузки: в приведенном ниже примере мы предварительно загружаем все включенные модули, если соединение хорошее.
import { Observable , of } from 'rxjs' ;
export class CustomPreloading implements PreloadingStrategy {
public preload ( route : Route , load : ( ) => Observable < any > ) : Observable < any > {
return preloadingConnection ( ) ? load ( ) : of ( null ) ;
}
}
const routing : ModuleWithProviders = RouterModule . forRoot ( routes , {
preloadingStrategy : CustomPreloading
} ) ;Обратите внимание, что приведенный выше пример не будет очень эффективным для более крупных приложений, так как он будет предварительно загружать все модули.
https://angular.io/api/router/preloadstrategy, https://vsavkin.com/angular-router-peloading-modules-ba3c75e424cb,https://medium.com/@adrianfaci U/Custom-Preloading Strategy-For-Angular-Modules-B3B5C873681A, https: //coryrylan.com/blog/custom-peloading-and-lazy-strategies-with-angular
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: маршрутизатор
Можно использовать теги SVG в вашем угловом компоненте, для создания красивых графиков и визуализаций. Есть 3 вещи, которые вам нужно знать:
attr < circle [attr.cx] =" x " [attr.cy] =" y " > </ circle >// Not: < child-component > </ child-component >
< g child-component > </ g > @ Component ( { selector : '[child-component]' } )@ Component ( {
selector : '[child-component]' ,
template : `<svg:circle></svg:circle>`
} )
Интерактивная демонстрация этого фрагмента | ⬆ Вернуться к вершине | Теги: Совет SVG