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

Ваше первое (и, возможно, последнее) приложение на Angular

Вы помните, как писали свою первую программу на Python? Вероятно, это был радостный момент, связанный с созданием простого однострочника под названием hello.py:

print("Hello World!")

Так просто! Один файл, одна строка, и он работает на любой версии Python 3.

Что касается вашего первого приложения на Angular ... вы знакомы с HTML, JavaScript и Typescript, у вас есть удобные носки и 2 часа свободного времени. После просмотра некоторых руководств вы, вероятно, решили погрузиться в самую суть, набрав ng new. Если вы использовали React в прошлом, вы, вероятно, ожидали, что у вас будет автономный файл .js / .ts, который будет обслуживаться вашим любимым серверным менеджером шаблонов.

Продолжайте, введите ng new my-first-app. Попробуй.

После ответа на несколько безобидных вопросов и нажатия клавиши Enter ваша консоль взрывается в ярости от компиляции и создания файлов. 10 секунд и 31 файл спустя, у вас есть «Hello World!» Создано угловое приложение.

К сожалению, именно здесь начинается большинство уроков и заканчивается энтузиазм.

Ваше второе первое приложение

Angular - это бегемот. Он имеет встроенный набор тестов, репозиторий git, файлы конфигурации линтера, файлы установки Angular prod / dev и даже подготавливает вашу среду Node. Может быть, в будущих версиях у вас будут налоги. Позже в будущем все это может быть супер-круто, но для того, кто просто хочет пример Hello World, это может вызвать беспокойство.

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

Если хотите что-то более легкое, попробуйте ng new my-second-app --minimal --skip-git. Это создает наш новый проект без тестирования, git, и сохраняет файлы шаблонов .html, встроенные в фактический скрипт. Это не совсем «баребоны», но я надеюсь, что теперь вы знаете, что Angular не является «баребонами».

Используя силу игнорирования вещей, наше приложение теперь состоит только из двух файлов!: app.module.ts и _7 _. (И если бы мы действительно хотели, мы могли бы объединить их). Что касается других файлов, пока не беспокойтесь о них. Они здесь по какой-то причине. Вы обнаружите, что Angular похож на приложение Flask, Django или Kivy, или любой другой фреймворк, который выполняется какими-то таинственными внутренними силами. Вы определяете функции и классы, но их выполняет что-то другое. Это поведение контролируется файлами, которые мы игнорируем.

Простая структура приложения

app.module.ts - Определения проекта

Большинство языков программирования общего назначения имеют похожий формат. Некоторый импорт, некоторые объявления классов и некоторые функции. Angular не исключение; Если вы занимались объектно-ориентированным программированием на Python или работали с такими фреймворками, как Flask, это должно показаться вам знакомым.

Взгляните на app.module.ts, который определяет структуру всего нашего приложения:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule(
  {
    declarations: [AppComponent],
    imports: [BrowserModule],
    providers: [],
    bootstrap:[AppComponent]
  }
)
export class AppModule { }

Здесь нет HMTL, только некоторый импорт и пустой (но украшенный) класс. Пересматривая импорт:

  1. BrowserModule - Не знаю, что это делает, но пока в этом нет необходимости.
  2. NgModule - это декоратор, используемый в коде, и часть ядра Angular. Как и Flask в Python, настоящая магия работает в Angular с помощью декораторов. Это говорит Angular, что это отправная точка вашего приложения.
  3. AppComponent - Это ваше приложение! Или, по крайней мере, это компонент вашего приложения. Как и app.module.ts,, он находится в каталоге /src/app. Он предоставляет наш AppComponent класс, который мы изменим, чтобы изменить наш веб-сайт.

Далее в app.module.ts идет реальный код.

Это похоже на беспорядок (сначала), но при ближайшем рассмотрении, по крайней мере, знакомо. Сам класс ничего не делает. Декоратор @NgModule превращает этот пустой класс в модуль Angular и определяет declarations, imports, providers и bootstrap. Декораторы в TypeScript очень похожи на декораторы в Python; они просто изменяют объект / функцию, которую украшают. В этом случае декоратор добавляет некоторые свойства, специфичные для Angular, и делает его похожим на модуль Angular. Можно написать это без декораторов, но я думаю, что это намного чище. Почему Angular предпочел декораторы наследованию или экземплярам своих собственных предопределенных классов? Кто знает. В любом случае:

  1. declarations - это список всех компонентов в нашем приложении Angular. Прямо сейчас у нас есть только один.
  2. imports - это импорт или пакеты, необходимые для компонентов.
  3. providers - это классы, которые Angular подготовит и внедрит в компоненты. В разделе «Бонус: конструкторы» этой статьи CookieService будет включен в качестве поставщика.
  4. bootstrap - точка входа для вашего приложения. В данном случае это AppComponent, как определено в app.component.ts.

app.module.ts нет ничего слишком впечатляющего; в первую очередь это определяет масштаб нашего проекта. Фактический веб-сайт можно найти на app.component.ts.

app.component.ts - Ваш веб-сайт

import { Component } from '@angular/core';
@Component(
  {
    selector: 'app-root',
    template: `<div>{{title}}</div>`,
    styles: []
  }
)
export class AppComponent {
    title = 'my-second-app';
}

Другой файл, та же история: оформленный класс. Однако вместо@NgModule стоит@Component. Компоненты - это фактические части, отображаемые на вашем веб-сайте. Атрибуты декоратора:

  1. selector - это HTML-тег, который будет заменен компонентом. В данном случае это app-root, что означает, что Angular найдет <app-root></app-root> в index.html одном каталоге выше - да, мы только что выяснили, что делает один из этих файлов!
  2. templateUrl - это HTML-шаблон для этого Компонента. Если вы сделали --minimal, это будет фактический HTML (который я заменил на <div>{{title}}</div> для краткости. Если вы этого не сделали, это будет шаблон .htmlfile.
  3. styleUrls - Полное раскрытие, я не специалист по UI / UX (пока?), И я презираю работу с CSS. Но вот где вы его найдете.

Угловой компонент - это просто объект

Итак, HTML находится в отдельном файле / BLOB-объекте, который определяется в декораторе… что же тогда делает настоящий класс?

Конечно же, запускает наш код! Сейчас это всего одна строка: title = my first app. Представим на секунду, что Angular был написан для Python. В этом случае (полное раскрытие, я никогда не использовал декоратор классов в Python) наш код, приведенный выше, будет выглядеть так:

from Angular.core import Component
@Component(
    selector="app-root",
    templateURL="""<div>{{title}}</div>""",
    styleUrls=[]
)
class AppComponent():
   title="my-second-app"

Приложение Python-Angular было бы на удивление похожим. Сравнивая TypeScript с Python, становится очевидно, чтоtitle - это просто свойство класса TypeScript (или атрибут класса Python). И вот важное замечание: наш HTML-шаблон имеет доступ к свойствам класса.

Еще раз взгляните на «минимальный» текст шаблона и обратите внимание на элемент {{title}}, встроенный в HTML. Вероятно, очевидно, что это отображает заголовок страницы и что за это отвечают фигурные скобки. Но что именно происходит?

  1. Фигурные скобки в Angular указывают на одностороннюю привязку приложения к представлению. Если AppComponent.title изменится, изменится и {{title}}. Привыкайте слышать про «привязку»; это просто означает, что одно (например, приложение angular) вызывает изменение другого (например, веб-страницы).
  2. Так почему {{title}} не нужно указывать this., self. или AppComponent. перед названием свойства? Потому что шаблон живет внутри класса! Декоратор вводит это как свойство класса. Фактически, HTML может видеть только переменные, принадлежащие его собственным классам!

Компоненты Angular имеют методы класса

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

Давайте создадим кнопку, которая вызывает метод класса и меняет заголовок на «Clicked Title»:

import { Component } from '@angular/core';
@Component(
  {
    selector: 'app-root',
    template: `<button (click) = "newTitle()">{{title}}</button>`,
    styles: []
  }
)
export class AppComponent {
    title = 'my-second-app';
    newTitle() {
      this.title = 'Clicked Title';
      console.log('Title was changed!');
    }
}

На нашем воображаемом языке Python Angular это может выглядеть так:

from Angular.core import Component
@Component(
    selector="app-root",
    templateURL="""
      <button (click) = "newTitle()">
        {{title}}
      </button>""",
    styleUrls=[]
)
class AppComponent():
  title="my-second-app"
  def newTitle(self):
    self.title="Clicked Title"
    print("Title was changed!")

Большой! В нашем HTML-большом двоичном объекте мы можем получить доступ к методам класса! И методы класса, конечно, могут обращаться к свойствам класса! Обратите внимание на () вокруг свойства click. Скобки указывают Angular, что он ищет метод класса для создания события - в данном случае это’sAppComponent.newTitle().

Бонус: конструкторы (также известные как __init __ ())

Часто библиотеки и функции необходимо импортировать в компоненты. Возьмем, к примеру, CookieService, который обрабатывает сохранение и получение переменных как файлов cookie. Вместо pip install ngx-cookie-service это npm install ngx-cookie-service.

Если мы установим эту библиотеку и включим ее в наш пример:

import { Component } from '@angular/core';
import { CookieService } from 'ngx-cookie-service';
@Component(
  {
    selector: 'app-root',
    template: `<div></div>`,
    styles: []
  }
)
export class AppComponent {
    title = 'cookie-test';
    
    constructor( private cookieService: CookieService ) { }
    newTitle() {
      this.title = 'Clicked Title';
      console.log('Title was changed!');
      this.cookieService.set('title', this.title);
      this.title = this.cookieService.get('title');
    }
}

В нашем воображаемом проекте Python Angular это может выглядеть так:

from Angular.core import Component
from ngx_cookie_service import CookieService
@Component(
    selector="app-root",
    templateURL="""<div></div>""",
    styleUrls=[]
)
class AppComponent():
  title="my-second-app"
  def __init__(self, cookieService: CookieService):
    self.cookieService = cookieService
  def newTitle(self):
    self.title = "Clicked Title"
    print("Title was changed!")
    self.cookieService.set('title', self.title)
    self.title = self.cookieService.get('title')

constructor - это просто __init__ в Python! В примере Angular cookieService будет поставщиком в app.module.ts, который будет внедрен в AppComponent с помощью типов TypeScript. В примере с Python мне пришлось бы использовать подсказку типа, чтобы указать нашему воображаемому бэкэнду Angular, что это должен быть объект CookieService.

Кроме того, вы правы: приведенный выше пример не дает ничего полезного.

То же, но другое

Python и Angular, очевидно, совершенно разные звери, но все объектно-ориентированное программирование в некоторой степени похоже. В любом случае у вас есть класс, атрибуты и методы класса. А весь Angular - это просто объектно-ориентированное программирование.

Если есть что-то, что вы должны убрать из этого, просто помните: Angular Component - это просто класс!

Дальнейшее чтение

С таким новым мировоззрением, почему бы не взглянуть еще раз на Учебник Tour of Heroes Angular?

Также не забудьте освежить в памяти:

  1. Объектно-ориентированное программирование на Python
  2. Машинописное объектно-ориентированное программирование