Я работаю над angular уже несколько недель, и мне было интересно, как я могу написать чистый компонент без слишком большой зависимости и большого повторного использования.
Я должен сказать, что моя проблема связана с большой архитектуройгде вещи уже существуют.
Допустим, мне нужно написать компонент, который отображает выбор с помощью 2 переключателей: либо вы можете выбрать «Плейлист 1» или «Плейлист 2».Этот компонент имеет службу с именем «PlayerService», которая имеет метод «Play», который принимает массив композиций.Идея состоит в том, чтобы выбрать «Playlist 1» или «Playlist 2» и, нажав кнопку, вызвать PlayerService с правильным Playlist.
Вот базовая реализация: этот код только для демонстрации.
BasicComponent.ts
import { PlayerService } from '../services/player.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-basic',
templateUrl: './basic.component.html',
styleUrls: ['./basic.component.css']
})
export class BasicComponent implements OnInit {
private playlistArray = [
{ name: "playlist1", sounds: ["sound1.mp3", "sound2.mp3"]},
{ name: "playlist2", sounds: ["sound2.mp3", "sound3.mp3", "sound4.mp3"]}
]
public SelectedPLayListName: string;
constructor(private playerService: PlayerService) { }
ngOnInit() {
}
onPlayButtonClicked(): void {
var playList = this.playlistArray.find(x => x.name == this.SelectedPLayListName);
this.playerService.Play(playList.sounds);
}
}
PlayerSercice.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PlayerService {
constructor() {}
public Play(sounds: any[]): void {
console.log("Start Play on a Playlist containing " + sounds.length + " elements");
}
}
Итак, как я уже говорил выше, у нас есть BasicComponentкоторые имеют 2 списка воспроизведения в массиве, 2 переключателя и кнопку, чтобы подтвердить выбор.При проверке компонент выдает правильный массив PlayerService.
Это не то поведение, которое я хотел бы / я могу реализовать на основе текущей архитектуры проекта.
BasicComponentне может иметь массив PlayList в своем собственном классе.Вместо этого я хотел бы иметь возможность предоставить ему массив списков воспроизведения из родительского компонента в качестве входных данных для примера.Это можно сделать легко, объявив @Input и т. Д. И т. Д.
Это не то поведение, которое я хотел бы / я могу реализовать на основе текущей архитектуры проекта.
Я не хочу, чтобы у моего BasicComponent был PlaylistArray как @Input, я хочу только один объект списка воспроизведения.Тот, который мой пользователь выбрал, щелкнув по переключателю ВНУТРИ моего BasicComponent.Поэтому я хотел бы, чтобы мой BasicComponent мог отображать выбор между Playlist1 и Playlist2, затем каким-то образом запросить правильный список воспроизведения у его родителя и передать его PlayerService
Я придумал 2 способа сделать это:
- @ Input / @Output:
- Получение списка воспроизведения из родительского компонента с помощью параметра @Input.
- Затем при щелчке пользователяPlayButton, BasicComponent "испускает свой @Ouput" с именем "OnPlay" с именем выбранного списка воспроизведения в качестве аргумента
- Родитель реагирует на этот @Output и получает хороший список воспроизведения и устанавливает его в качестве входных данных для BasicComponent
- BasicComponent реализует логику, которая обнаруживает изменение на входе, и если оно изменяется, потому что мы генерировали выход, то он может вызвать метод воспроизведения в службе с этим списком воспроизведения.
Я думаю, что есть много уродливого кода, вызывающего это, в основном из-за этой задержки между @ output.emit и фактическим chАнж @input.Эта идея не очень хорошая, но я подумал об этом.
- @ Ввод службы:
- Создание интерфейса IPlayListProvider, который содержитМетод GetPlayList (name: string).
- Создание службы PlayListProvider и Inherit из IPlayListProvider.
- Создание @Input в моем BasicComponent типа IPlayListProvider.
- Таким образом, родитель может иметь (из DI в конструкторе) и хранить экземпляр PlayListProvider.
- Таким образом, родительский объект может передать этот экземпляр в службу в качестве входных данных для BasicComponent.
- BasicComponent теперь может вызывать метод GetPlayList с SelectedPlayListName в выборе переключателя, когда пользователь нажимает PlayButton.
Мне нравится эта реализация, потому что этот сервис не очень связан с моим BasicComponent, я могу повторно использовать свой компонент и предоставить другой сервис, который также реализует этот интерфейс, и он будет работать.Я могу хранить все, где они должны быть, даже если мне потребуется выполнить некоторую логику, чтобы служба PlayListProvider могла получать список воспроизведения, где бы они ни находились.Единственное, я не знаю, может ли это делать Dangerous, может ли это сломать вещи в моих проектах Angular, если это противоречит лучшей практике Angular.
Или, может быть, есть другой способ? (что держит вещи отдельно, и мой компонент можно использовать повторно)
Что вы думаете? Как бы вы это сделали?
Редактировать 1:
В моей исходной почтовой версии я не говорил о своем требовании:
На самом деле у меня есть такая реализация в существующем коде. «Родительский компонент» уже существует и не хранит какой-либо список воспроизведения, но у него есть службы, которые можно использовать для получения списка воспроизведения по имени.
По бизнес-требованиям я не могу напрямую использовать эту услугу внутри своих компонентов. Я должен пройти через этот родительский компонент, я могу изменить родительский компонент, но не слишком сильно, это не структура или поведение.
Поэтому моему компоненту нужно для работы в качестве «промежуточного программного обеспечения», предоставляющего выбор, и запрашивающего данные для другой службы или компонента и передающего их в проигрыватель. Более того, эта система ввода должна быть многократно используемой, я должен иметь возможность взять этот компонент и, скажем, превратить его в новый проект, и он должен работать здесь без каких-либо изменений внутри этого компонента.
Это большое ограничение, но это ограничение, которое я не могу сломать.