NativeScript Angular集成 #
Angular 集成概述 #
NativeScript 与 Angular 深度集成,让你可以使用 Angular 的完整生态系统开发原生应用。
text
┌─────────────────────────────────────────────────────────────┐
│ Angular NativeScript │
├─────────────────────────────────────────────────────────────┤
│ │
│ 核心特性 │
│ ├── 完整的 Angular 支持 │
│ ├── TypeScript 原生支持 │
│ ├── 依赖注入 │
│ ├── 路由系统 │
│ ├── 表单处理 │
│ └── HTTP 客户端 │
│ │
│ NativeScript 扩展 │
│ ├── 原生 UI 组件 │
│ ├── 原生路由 │
│ └── 原生模块 │
│ │
└─────────────────────────────────────────────────────────────┘
项目创建 #
创建 Angular 项目 #
bash
ns create my-app --ng
项目结构 #
text
my-app/
├── src/
│ ├── app/
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ ├── app.module.ts
│ │ ├── app.routing.ts
│ │ └── home/
│ │ ├── home.component.html
│ │ ├── home.component.ts
│ │ └── home.module.ts
│ ├── environments/
│ ├── main.ts
│ └── styles.css
├── angular.json
├── package.json
└── tsconfig.json
模块配置 #
AppModule #
typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { NativeScriptModule } from '@nativescript/angular';
import { AppRoutingModule } from './app.routing';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
@NgModule({
declarations: [AppComponent, HomeComponent],
imports: [
NativeScriptModule,
AppRoutingModule
],
bootstrap: [AppComponent]
})
export class AppModule {}
启动应用 #
typescript
// main.ts
import { platformNativeScriptDynamic } from '@nativescript/angular';
import { AppModule } from './app.module';
platformNativeScriptDynamic().bootstrapModule(AppModule);
组件开发 #
基本组件 #
typescript
// home.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'ns-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
title = 'Home';
items: string[] = [];
ngOnInit() {
this.items = ['Item 1', 'Item 2', 'Item 3'];
}
onItemTap(item: string) {
console.log('Tapped:', item);
}
}
xml
<!-- home.component.html -->
<ActionBar title="Home">
<ActionItem text="Add" (tap)="onAdd()"></ActionItem>
</ActionBar>
<GridLayout>
<ListView [items]="items" class="list-group">
<ng-template let-item="item">
<Label [text]="item" class="list-group-item" (tap)="onItemTap(item)"></Label>
</ng-template>
</ListView>
</GridLayout>
组件通信 #
typescript
// 父组件
@Component({
selector: 'ns-parent',
template: `
<GridLayout>
<ns-child [data]="data" (dataChange)="onDataChange($event)"></ns-child>
</GridLayout>
`
})
export class ParentComponent {
data = 'Hello';
onDataChange(newValue: string) {
this.data = newValue;
}
}
// 子组件
@Component({
selector: 'ns-child',
template: `
<Label [text]="data" (tap)="onChange()"></Label>
`
})
export class ChildComponent {
@Input() data: string;
@Output() dataChange = new EventEmitter<string>();
onChange() {
this.dataChange.emit('New Value');
}
}
路由配置 #
路由定义 #
typescript
// app.routing.ts
import { NgModule } from '@angular/core';
import { Routes } from '@angular/router';
import { NativeScriptRouterModule } from '@nativescript/angular';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{
path: 'detail/:id',
component: DetailComponent,
canActivate: [AuthGuard]
},
{ path: 'settings', loadChildren: () => import('./settings/settings.module').then(m => m.SettingsModule) }
];
@NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule {}
路由导航 #
typescript
import { Router, ActivatedRoute } from '@angular/router';
@Component({
// ...
})
export class HomeComponent {
constructor(private router: Router) {}
goToDetail(id: number) {
this.router.navigate(['/detail', id]);
}
goToSettings() {
this.router.navigate(['/settings']);
}
}
@Component({
// ...
})
export class DetailComponent implements OnInit {
id: number;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.id = +this.route.snapshot.paramMap.get('id');
// 或订阅参数变化
this.route.paramMap.subscribe(params => {
this.id = +params.get('id');
});
}
}
路由守卫 #
typescript
// guards/auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) {}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
依赖注入 #
服务定义 #
typescript
// services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiUrl = 'https://api.example.com';
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(`${this.apiUrl}/users`);
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`${this.apiUrl}/users/${id}`);
}
createUser(user: CreateUserDto): Observable<User> {
return this.http.post<User>(`${this.apiUrl}/users`, user);
}
}
使用服务 #
typescript
@Component({
selector: 'ns-users',
templateUrl: './users.component.html'
})
export class UsersComponent implements OnInit {
users: User[] = [];
constructor(private userService: UserService) {}
ngOnInit() {
this.loadUsers();
}
loadUsers() {
this.userService.getUsers().subscribe(users => {
this.users = users;
});
}
}
表单处理 #
模板驱动表单 #
typescript
// app.module.ts
import { NativeScriptFormsModule } from '@nativescript/angular';
@NgModule({
imports: [
NativeScriptModule,
NativeScriptFormsModule
]
})
export class AppModule {}
xml
<!-- login.component.html -->
<GridLayout>
<StackLayout>
<TextField [(ngModel)]="email" hint="Email" keyboardType="email"></TextField>
<TextField [(ngModel)]="password" hint="Password" secure="true"></TextField>
<Button text="Login" (tap)="onLogin()"></Button>
</StackLayout>
</GridLayout>
typescript
// login.component.ts
@Component({
selector: 'ns-login',
templateUrl: './login.component.html'
})
export class LoginComponent {
email = '';
password = '';
constructor(private authService: AuthService) {}
onLogin() {
this.authService.login(this.email, this.password);
}
}
响应式表单 #
typescript
// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
NativeScriptModule,
ReactiveFormsModule
]
})
export class AppModule {}
typescript
// register.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'ns-register',
templateUrl: './register.component.html'
})
export class RegisterComponent {
registerForm: FormGroup;
constructor(private fb: FormBuilder) {
this.registerForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(6)]],
confirmPassword: ['', Validators.required]
}, { validators: this.passwordMatchValidator });
}
passwordMatchValidator(form: FormGroup) {
const password = form.get('password');
const confirmPassword = form.get('confirmPassword');
return password.value === confirmPassword.value ? null : { mismatch: true };
}
onSubmit() {
if (this.registerForm.valid) {
console.log(this.registerForm.value);
}
}
}
xml
<!-- register.component.html -->
<GridLayout>
<StackLayout [formGroup]="registerForm">
<TextField formControlName="name" hint="Name"></TextField>
<Label *ngIf="registerForm.get('name').errors?.required" text="Name is required" color="red"></Label>
<TextField formControlName="email" hint="Email" keyboardType="email"></TextField>
<Label *ngIf="registerForm.get('email').errors?.email" text="Invalid email" color="red"></Label>
<TextField formControlName="password" hint="Password" secure="true"></TextField>
<TextField formControlName="confirmPassword" hint="Confirm Password" secure="true"></TextField>
<Button text="Register" (tap)="onSubmit()" [isEnabled]="registerForm.valid"></Button>
</StackLayout>
</GridLayout>
懒加载 #
懒加载模块 #
typescript
// settings/settings.module.ts
import { NgModule } from '@angular/core';
import { NativeScriptCommonModule } from '@nativescript/angular';
import { SettingsComponent } from './settings.component';
import { SettingsRoutingModule } from './settings.routing';
@NgModule({
declarations: [SettingsComponent],
imports: [
NativeScriptCommonModule,
SettingsRoutingModule
]
})
export class SettingsModule {}
typescript
// settings/settings.routing.ts
import { NgModule } from '@angular/core';
import { Routes } from '@angular/router';
import { NativeScriptRouterModule } from '@nativescript/angular';
import { SettingsComponent } from './settings.component';
const routes: Routes = [
{ path: '', component: SettingsComponent }
];
@NgModule({
imports: [NativeScriptRouterModule.forChild(routes)],
exports: [NativeScriptRouterModule]
})
export class SettingsRoutingModule {}
最佳实践 #
组件命名 #
text
┌─────────────────────────────────────────────────────────────┐
│ 命名规范 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 组件 │
│ ├── 文件名: user-list.component.ts │
│ ├── 类名: UserListComponent │
│ └── 选择器: ns-user-list │
│ │
│ 服务 │
│ ├── 文件名: user.service.ts │
│ └── 类名: UserService │
│ │
│ 模块 │
│ ├── 文件名: user.module.ts │
│ └── 类名: UserModule │
│ │
└─────────────────────────────────────────────────────────────┘
下一步 #
现在你已经掌握了 Angular 集成,接下来学习 Vue集成,了解如何与 Vue 框架集成!
最后更新:2026-03-29