Angular2 - 组件





5.00/5 (7投票s)
Angular2 - 组件
在哪里可以找到本文的示例代码?
请在 https://github.com/techcoaching/angular2.git 的 "feature/angular2-component" 分支中查看代码。
Angular2 中的组件是什么?
总体来说,为了方便理解,组件就是一个我们想要显示的页面。
在显示我的组件/页面时,是否需要向 Angular 注册?
是的,在 userRoute.ts 中,我们向 Angular 注册当导航到特定 URI 时将渲染哪个组件。
例如
{ path: 'users', component: Users }
这将告诉 Angular,当用户导航到 "<rootUrl>/users" 时,将显示 Users
组件,并且用户列表将如下所示渲染到浏览器:
好的,在代码中,我们只是注册了一个 ts 类(名为 Users)。Angular 如何知道应该渲染哪个 UI?
我明白了,如果我们更深入地查看 Users
类的定义。
@Component({
templateUrl: "src/users.html"
})
export class Users {}
正如 Users
类的定义中,有一个 @Component
装饰器,其参数对象中有一个 templateUrl
属性。
@Component({
templateUrl: "src/users.html"
})
Angular 将使用 "src/users.html" 的内容作为 Users
组件的标记。
是否有其他方法指定组件的 HTML 内容?
是的,有两种方法可以指定 Angular 组件的标记:
- 使用
templateUrl
:这是包含该组件标记的 HTML 文件的路径。 - 使用:
template
:这包含作为string
的组件标记。
我将 @Component
装饰器修改如下:
@Component({
template: "<div>this is inline template</div>"
})
然后 "<root url>/users
" 渲染如下:
我应该为我的组件使用 template 还是 templateUrl?
这取决于您。但我建议,如果您的组件需要简短的 HTML(2 或 3 行),那么可以使用 template
属性。否则,我们应该使用 templateUrl
属性。
如何在 Angular 组件中构造模板文件的路径?
例如,对于 Users
组件,路径是 "src/users.html"。
路径是从应用程序根目录计算的。在这种情况下,它与 index.html 在同一个文件夹。
请注意,我们在 index.html 文件中有一个 "<base />
" 标签。此标签定义了应用程序如何解析到指定资源的路径(HTML、CSS、图像等)。
那么 "selector" 属性呢?
请暂时忽略此属性,我们将在 "Angular2 - 指令" 文章中再次讨论它。
如何在 HTML 模板文件中显示数据?
我们需要在 Users
类中定义 "users
" 属性。此属性包含将在 UI 上显示的用户信息。
以下步骤向您展示了如何在 HTML 文件中显示数据:
在 users.html 文件中:
<div>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users">
<th scope="row">{{user.id}}</th>
<td>{{user.firstName}}</td>
<td>{{user.lastName}}</td>
<td>{{user.userName}}</td>
<td>
<a title=""><i class="fa fa-edit"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
注意:在 HTML 文件中,我们可以访问 ts
类中的 public
属性(例如:本例中的 users
)。
在 users.ts 中:
@Component({
templateUrl: "src/users.html"
})
export class Users {
public users: Array<any> = [
{id:1, firstName:"Tu", lastName:"Tran", userName:"tutran"},
{id:2, firstName:"Tu 1", lastName:"Tran", userName:"tutran2"},
{id:3, firstName:"Tu 2", lastName:"Tran", userName:"tutran3"}
];
}
在 ts
类中,我们需要将其声明为 public
属性并为其设置值。
我尝试将 Users 声明为私有属性。它仍然有效。我的代码有什么问题?
不,您的代码是正确的。
打开与 users.ts 同一个文件夹中的 users.js。我发现(无论是声明 public
还是 private
的 users),生成的 js 都是相同的。
Users = (function () {
function Users() {
this.users = [
{ id: 1, firstName: "Tu", lastName: "Tran", userName: "tutran" },
{ id: 2, firstName: "Tu 1", lastName: "Tran", userName: "tutran2" },
{ id: 3, firstName: "Tu 2", lastName: "Tran", userName: "tutran3" }
];
}
return Users;
}());
这就是为什么 public
或 private
不影响页面功能的原因。我猜这是 typescript 编译器 (tsc) 的一个错误。
此时,我们在 Users.ts 类中定义了用户列表。如何将此逻辑提取到外部类并在 users.ts 文件中调用它?
好的,为此,我们需要定义一个新的类(命名为 UserService
)并在 Users
类中像下面这样调用它:
在 userService.ts 中定义 getUsers
方法:
export class UserService {
public getUsers(): Array<any> {
let users: Array<any> = [
{ id: 1, firstName: "Tu", lastName: "Tran", userName: "tutran" },
{ id: 2, firstName: "Tu 1", lastName: "Tran", userName: "tutran2" },
{ id: 3, firstName: "Tu 2", lastName: "Tran", userName: "tutran3" }
];
return users;
}
}
并在 Users
类(在 users.ts 中)中调用它:
export class Users {
private users: Array<any> = [];
constructor() {
let userService = new UserService();
this.users = userService.getUsers();
}
}
我们还需要使用 import
语句在 Users
类的顶部导入 UserService
类。
import { UserService } from "./userService";
通过这种方式,我需要手动创建一个新的 User Service 实例,Angular 能为我创建吗?
是的,在 Angular 中,我们有依赖注入 (DI) 的概念。这意味着 Angular 会查找所需的类并为您创建合适的实例。然后,我们可以在该实例上调用相应的方法。
我们还需要声明 Users
和 UserService
类之间的依赖关系。
好的,听起来很有趣。您能告诉我如何在 Angular 中使用 DI 吗?
好的,首先,我们需要像下面这样修改 Users
类(在 users.ts 中):
export class Users {
private users: Array<any> = [];
constructor(userService: UserService) {
this.users = userService.getUsers();
}
}
注意
- 在
Users
类的构造函数中(在 users.ts 中),我们将userService
声明为UserService
类型。 - 并调用此
userService
的getUsers()
来获取用户列表,而无需再创建UserService
的新实例。
如果我们再次运行应用程序。Angular 会像图片一样抛出一个错误:
Angular 不理解 UserService
是什么。要解决此问题,我们需要在 @Component
装饰器中添加 "providers
",如下所示:
@Component({
...,
providers: [UserService]
})
因此,此时 Users
的完整代码如下:
@Component({
selector: "users",
templateUrl: "src/users.html",
providers: [UserService]
})
export class Users {
private users: Array<any> = [];
constructor(userService: UserService) {
this.users = userService.getUsers();
}
}
让我们再次编译并运行,应用程序运行良好,没有任何错误。
这很好。但我不想在所有组件中都注册 UserService 类。有其他解决方案吗?
是的,在应用程序中,我们可以有一个或多个模块(使用 @NgModule
装饰器声明)。每个组件都在指定的模块中注册。
因此,我们可以在声明了 Users
组件的 @NgModule
中声明 UserService
。
打开 UserModule
类(在 userModule.ts 中),添加 providers
属性,如下所示:
@NgModule({
imports: [
BrowserModule,
FormsModule,
UserRoutes
],
declarations: [Users, CreateUser, EditUser, Layout],
bootstrap: [Layout],
providers: [UserService]
})
现在,在 Users
中,我们可以从 @Component
装饰器中删除 providers
。
@Component({
selector: "users",
templateUrl: "src/users.html"
})
编译并刷新浏览器,用户页面运行良好。
我仍然对代码不满意,因为我们直接使用了 UserService 类。我期望应用程序通过 IUserService 接口使用 UserService 的功能。我该怎么做?
不,我们不能将接口注入为依赖项。
export class Users {
private users: Array<any> = [];
constructor(userService: IUserService) {
}
}
这行不通,因为接口是 TypeScript 的定义,JavaScript 不理解接口。这些接口将在将 TypeScript 代码编译成 JavaScript 代码以运行应用程序时被移除。
因此,在运行时,Angular 无法使用接口。
感谢您的阅读。