typescript - 在 Angular 2 的类中使用服务
我想在我的课堂(模型)中使用一项服务
在我的课程中使用服务
movie-list.component.ts
import { Component, OnInit } from '@angular/core';
import {Movie} from "../../models/movie";
import {MovieService} from "../../services/movie.service";
@Component({
selector: 'movie-list',
templateUrl: './movie-list.component.html',
})
export class MovieListComponent implements OnInit {
public movies = [];
public movie: Movie;
constructor(private movieService: MovieService) {
this.movie = new Movie();
}
ngOnInit() {
console.log(this.movie.getMovies());
this.movies = movie.getMovies();
}
}
movie-list.component.html
<div *ngFor="let movie of movies">
{{ movie.title }}
<div *ngFor="let actor of movie.actors">
{{ actor.name }} - {{ actor.getOscar() }}
</div>
</div>
movie.ts(电影模型)
import { Actor } from "./actor";
export class Movie {
constructor(title: string = '', actors: any = []) {
this.title = title;
this.actors = [];
}
title: string = '';
actors: any = [];
movieService;
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
let movie = new Movie(
data.title,
data.actors
);
movie.setModel({ actors: []});
data.actors.forEach((actor) => {
let new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
let movies: any[];
this.movieService.getMovies().subscribe(
data => {
data.map((result) => {
movies.push(this.build(result));
});
return movies;
},
error => {
console.error(error);
}
)
}
}
actor.ts(actor 模型)
export class Actor {
constructor(firstname: string, lastname: string) {
this.firstname = firstname;
this.lastname = lastname;
}
firstname: string;
lastname: string;
setModel(obj) {
Object.assign(this, obj);
}
getOscar() {
return '10 oscars';
};
}
movie.service.ts
import { Injectable } from '@angular/core';
import {Http} from "@angular/http";
import 'rxjs/add/operator/map';
@Injectable()
export class MovieService {
constructor(private http:Http) { }
getMovies() {
return this.http
.get('data/movies.json')
.map(res => res.json());
}
}
movies.json
[
{
"title": "title1",
"actors": [
{
"firstname": "firstname10",
"lastname": "lastname10"
},
{
"firstname": "firstname11",
"lastname": "lastname11"
}
]
},
{
"title": "title2",
"actors": [
{
"firstname": "firstname20",
"lastname": "lastname20"
},
{
"firstname": "firstname21",
"lastname": "lastname21"
}
]
}
]
我想在我的类中“注入/使用”我的服务,以使用此工作流:
- 组件(在我的类中调用 getMovies)
- 类(在我的服务中调用 getMovies,用响应构建我的对象(电影,演员)通过 this.build)
- 服务(调用我的 API,返回 JSON,不使用类型对象(电影,演员))
我尝试在我的类中使用 @inject,但它不起作用,来自这篇文章:如何将服务注入到类(不是组件)
我想知道做到这一点的最佳做法。
使用这段代码,我遇到了一个错误:
修改
在我的组件中添加了这个:
constructor(private movieService: MovieService) {
this.movie = new Movie();
this.movie.movieService = movieService; // add this line
}
我的组件在这一行出现了一个错误:
ngOnInit() {
console.log(this.movie.getMovies());
this.movies = movie.getMovies(); // error Type 'void' is not assignable to type 'any[]'.
}
我希望在模型中保留订阅,以便在我的组件中保持代码整洁
已解决
movie-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Movie } from "../../models/movie";
import { MovieService } from "../../services/movie.service";
@Component({
selector: 'movie-list',
templateUrl: './movie-list.component.html',
})
export class MovieListComponent implements OnInit {
public movie: Movie;
public movies = [];
constructor(private movieService: MovieService) {
this.movie = new Movie('', []);
this.movie.movieService = movieService;
}
ngOnInit() {
this.movies = this.movie.getMovies();
}
}
电影.ts
import { MovieService } from "../services/movie.service";
import { Actor } from "./actor";
export class Movie {
constructor(
private title: string = '',
private actors: any[] = [],
) { }
public movieService : MovieService;
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
const movie = new Movie(
data.title,
data.actors,
);
movie.setModel({ actors: [] });
data.actors.forEach((actor) => {
const new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
let movies = [];
this.movieService.getMovies().subscribe(
data => {
data.map((result) => {
movies.push(this.build(result));
});
},
error => {
console.error(error);
}
);
return movies;
}
}
答案#1
你应该阅读关于 Smart 和 Presentation(Dumb)组件的内容。这无疑是最好的做法,因为整个 Angular 的数据管理和变更检测都围绕它展开。
http://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/
你的错误来自你在构造函数中设置的两个参数,因为这些参数应该通过 @Input 装饰器传递或者从服务中获取。你不能像 let foo=new MovieComponent(.., ...); 这样做,所以这是行不通的。
请阅读官方文档。这也会帮助你设置智能/傻瓜组件结构:
https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding
编辑:要使您的服务工作,只需将其作为依赖项传递到您的 MovieComponent 构造函数中,例如:
constructor(
private movieService: MovieService
) {}
别忘了在你的(我预计的)MovieModule中,或在声明MovieComponent的地方(在同一个模块中)提供你的MovieService
编辑2:以下是对我有用的代码部分。模型类需要重新设计,加入一个方法以异步返回构建的电影,但即便如此,我仍觉得那个模型不是很实用。你最好只使用接口和服务。此外,这显然不是智能/非智能组件的交互,因此需要进行一些升级以实现你想要的功能。
电影列表组件
export class MovieListComponent implements OnInit {
public movies = [];
public movie: Movie;
constructor(private movieService: MovieService) {
this.movie = new Movie('', []);
}
ngOnInit() {
this.movie.movieService = this.movieService;
this.movie.getMovies().subscribe(
data => {
data.map((result) => {
this.movies.push(this.movie.build(result));
});
}
);
}
}
电影(模型)
export class Movie {
movies: any[];
movieService: MovieService
constructor(
private title: string = '',
private actors: any[] = [],
) { }
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
const movie = new Movie(
data.title,
data.actors,
);
movie.setModel({ actors: [] });
data.actors.forEach((actor) => {
const new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
return this.movieService.getMovies();
}
}
模块
@NgModule({
imports: [
HttpModule,
CommonModule
],
declarations: [
MovieListComponent
],
providers: [
MovieService
]
})
export class MainModule { }
答案#2
传递一个提供它们的父注入器
constructor( parentInjector:Injector ){
let injector = ReflectiveInjector.resolveAndCreate ( [ ProductService ] );
this.productService = injector.get(ProductService, parentInjector);
}

