Angular2 单页应用的编写 by 嗡

来源:互联网 发布:数据铁笼技术方案 编辑:程序博客网 时间:2024/05/29 03:19

  • 单页应用的特点
    • 优势
    • 劣势
  • 程序编写
    • 开发环境
    • 新建项目
    • 主要概念
      • Component
        • componentts
        • componenthtml
        • componentts和componenthtml的关联和绑定数据和行为
      • 路由
        • 路由的声明
        • 路由实例
      • 服务
        • 实例将路由跳转封装为服务
          • step1 建立服务
          • step2实现服务方法
          • step3在appmodulets中引入服务
          • step4在component中注入服务
          • step5调用
  • 程序打包

Angular2 是一个All in one 的功能完备的框架,与上一版本Angular1.x 不同的地方在于:TypeScript(微软推出)成为了官方主推语言,同时引入了rxjs等框架,是程序编写更为严谨,效率更高;摒弃了$scope等复杂的元素简化为Component;内置更完整的路由功能,从而无需使用1.x时代的angular-ui-router等工具。

单页应用的特点

优势

  • 在用户访问时,仅请求一次页面和静态资源。后端应用可以专注于api接口请求的处理,减少了页面跳转的路由处理压力以及页面渲染压力,减少频繁请求静态资源的压力。
  • 页面切换不需要重新请求并渲染页面,减少了客户端页面切换的白屏问题,同时由于是本地路由加页面渲染,页面切换也更加迅速和流畅。
  • 编写调试时,页面app实时更新并展示最新效果,调试效率高。
  • 可以方便地移植到web、app中。

劣势

  • 首屏需要下载体积较大的静态资源(可以通过webpack打包工具进行压缩与精减)
  • 首屏需要启动应用,渲染较慢(Angular2支持预编译,起到加快启动速度的作用)

程序编写

开发环境

Angular2程序的编写需要使用nodejs(现在几乎是前端开发的必备工具了。。。),同时准备一个合适的IDE即可开始编写应用程序,我自己选用的是Visual Studio Code,插件管理和安装比较方便,功能相比Sublime Text也不差。
在nodejs和IDE准备完成后,启动一个控制台,或者直接通过Visual Studio Code的控制台操作即可。
这里写图片描述

其次,使用node的包管理工具npm安装angular-cli工具。这样在构建angular2应用和编译打包时候更加方便,否则还需要自行安装webpack并进行配置。

新建项目

通过命令行新建一个目录,比如:demoapp

mkdir demoappcd demo app 

使用angular-cli新建一个angular2应用,ng new demoapp ,此时,node会自动下载angular2所依赖的node模块(放在node_module中)。构建完成后的项目接口如图:
这里写图片描述

  • src/app文件夹中就是程序的主要代码
  • src/index.html是首屏页面,src/main.ts是启动入口
  • src/package.json为依赖管理配置
  • src/angular-cli.json为Angular项目的配置(全局样式、工具库等引入可以放在这里)
  • 其余文件请自行参考nodejs模块规范和angular文件规范

此时该项目已经是一个可以运行的初始项目了。通过执行ng serve 启动node服务,在浏览器中输入localhost:4200 即可预览。
这里写图片描述

项目启动流程大致如下:

  • [main.ts]载入根模块[app.module.ts]: platformBrowserDynamic().bootstrapModule(AppModule);
  • [app.module.ts]载入根Component: bootstrap: [AppComponent]
  • AppComponent就是页面中的”app works!”。

主要概念

Component

Component包括了页面逻辑、页面模板和样式文件,其共同定义了一个页面的视图、数据和逻辑。在基础项目中我们可以编写自己的Component了。

  • 在src/app文件夹下新建一个统一的Components目录。mkdir components, cd components
  • 通过angular-cli工具快速生成新Component。ng g component component1

新生成的Component结构如下:
这里写图片描述

component.ts

文件声明了模板路径、模板标签名称、数据、逻辑代码。

import { Component, OnInit } from '@angular/core';@Component({  selector: 'app-component1',  templateUrl: './component1.component.html',  // 也可以使用template:`<p>template content</p>`的方法使用模板,但是单独放在一个html文件中更方便编辑  styleUrls: ['./component1.component.css']})export class Component1Component implements OnInit {  constructor() { }  ngOnInit() {  }}

该文件表明了html中<app-compoment1> 是模板起作用的地方,数据和业务逻辑在该标签下起作用。这点和Angular1.x的directive很像。为方便了解这种ts文件的写法,推荐先自学了解一下TypeScript对于模块的声明和使用。看起来是不是很想Java或者C#?

component.html

文件内容如下:

<p>  component1 works!</p>

及页面中<app-component1></app-component1> 会被该模板内容取代。

component.ts和component.html的关联和绑定(数据和行为)

component.ts文件代码改为如下:

import { Component, OnInit } from '@angular/core';@Component({  selector: 'app-component1',  templateUrl: './component1.component.html',  styleUrls: ['./component1.component.css']})export class Component1Component implements OnInit {  constructor() { }  ngOnInit() {  }  modelValue:string = '';  message:string = 'This is a message';  buttonClicked():void {    alert('button clicked!');  }}

ts中声明了两个string变量和一个void方法。在html中进行如下修改:

<p>  {{message}}</p><input [(ngModel)]="modelValue" name="modelValue" /><p>your input is : {{modelValue}}</p><button (click)="buttonClicked()">click me</button>

效果将在后面展示。首先,我们先将该component在应用中显示出来。
目前应用进展示的根Component,因此需要把Component1变为根。
方法如下:
修改src/app.module.ts

import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { FormsModule } from '@angular/forms';import { HttpModule } from '@angular/http';import { AppComponent } from './app.component';// 引入component1import { Component1Component } from './components/component1/component1.component';@NgModule({  declarations: [    AppComponent,    Component1Component  ],  imports: [    BrowserModule,    FormsModule,    HttpModule  ],  providers: [],  //将根Component改为Component1  bootstrap: [Component1Component]})export class AppModule { }

修改应用首页html将标签从<app-root> 改为<app-component1>

<!doctype html><html><head>  <meta charset="utf-8">  <title>Demoapp</title>  <base href="/">  <meta name="viewport" content="width=device-width, initial-scale=1">  <link rel="icon" type="image/x-icon" href="favicon.ico"></head><body>  <!--<app-root>Loading...</app-root>-->  <app-component1></app-component1></body></html>

应用会自动刷新,效果如下:
这里写图片描述

可以看见message:string = 'This is a message'; 绑定已经起作用,第一个<p> 已经被替换为了message内容。

然后我们在input框中输入一些文字:
这里写图片描述

可以看到在用户输入文字时,下一行就实时显示了用户输入的结果。

我们单击按钮:
这里写图片描述

可以看到函数被触发。

这里仅仅是数据和行为绑定的简单例子,Angular1.x也有。但是Angular2和Angular1.x的区别在于Angular2支持单向传递数据和事件了,大大提升了应用脏值检测和页面渲染的性能。比如这里的() 代表传出,[] 代表传入,而[()] 代表双向绑定。具体请见Angular2的文档。

路由

路由负责应用内页面的跳转,是单页应用的核心之一。Angular2中可以通过<a routerLink="href"> 标签跳转页面,也可以在ts文件中通过代码的形式进行跳转。

路由的声明

路由模块在应用启动时声明和初始化完毕,我们可以为路由单独声明一个模块NgModule。代码如下

  • 新建一个模块app.routing.ts,包括了路径和Component之间的关系声明
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { Component1Component } from './components/component1/component1.component';const routes: Routes = [  { path: 'component1', component: Component1Component }];@NgModule({  imports: [RouterModule.forRoot(routes)],  exports:[RouterModule]})export class AppRoutingModule { }

在app.module.ts中引入路由模块:

import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { FormsModule } from '@angular/forms';import { HttpModule } from '@angular/http';//引入所有componentimport { AppComponent } from './app.component';import { Component1Component } from './components/component1/component1.component';//引入路由import { AppRoutingModule } from './app.routing';@NgModule({  declarations: [    AppComponent,    Component1Component  ],  imports: [    BrowserModule,    FormsModule,    HttpModule,    //引入路由    AppRoutingModule  ],  providers: [],  bootstrap: [AppComponent]})export class AppModule { }

同时需要在模板中添加路由管理的视图位置<router-outlet>

路由实例

我们将原根component恢复成原Component。
同时将根component的模板修改为:

<h1>  {{title}}</h1><a routerLink="component1">link-component1</a><button (click)="showComponent()">click to component1</button>// 路由管理的视图在这里显示<router-outlet></router-outlet>

根component.ts文件中引入路由组件和showComponent()方法

import { Component } from '@angular/core';//引入路由组件import { Router, ActivatedRoute } from '@angular/router';@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.css']})export class AppComponent {  //在构造函数中实例化组件  constructor(    private router:Router  ) {}  title = 'app works!';  showComponent(): void {    //路由跳转    this.router.navigate(['component1']);  }}

启动效果:
应用首页如下:
这里写图片描述
此时<router-outlet> 里没有视图。点击链接或者按钮分别通过两种方法另路由导入视图,效果如下:

这里写图片描述

可以看到地址栏由localhost:4200 变成了 localhost:4200/component1 ,页面中component1页显示了出来。

其余路由功能,请见Angular2文档。

服务

Angular2通过依赖注入来注入声明好的服务,良好的服务设计可以进一步使页面与逻辑分离,达到松耦合的效果。Angular2的依赖注入页Angular1.x不同,更加简洁清晰。大致步骤如下:

  • 声明服务ts文件,加入@Injectable注解。
  • 在app.module.ts中引入服务作为providers
  • 在使用服务的component中注入服务

实例:将路由跳转封装为服务

在上例中若对每个Component都单独引入路由组件并声明跳转方法非常费事也容易出错,我们可以将路由跳转单独封装为服务。

step1: 建立服务
//建立services文件夹,并新建routing服务mkdir servicescd servicesng g service routing
step2:实现服务方法
import { Injectable } from '@angular/core';import { Router, ActivatedRoute } from '@angular/router';@Injectable()export class RoutingService {  constructor(    private router: Router  ) { }  showComponent(): void {    this.router.navigate(['component1']);  }}
step3:在app.module.ts中引入服务
import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { FormsModule } from '@angular/forms';import { HttpModule } from '@angular/http';import { AppComponent } from './app.component';import { Component1Component } from './components/component1/component1.component';import { AppRoutingModule } from './app.routing';//引入服务import { RoutingService } from './services/routing.service';@NgModule({  declarations: [    AppComponent,    Component1Component  ],  imports: [    BrowserModule,    FormsModule,    HttpModule,    AppRoutingModule  ],  //引入服务  providers: [RoutingService],  bootstrap: [AppComponent]})export class AppModule { }
step4:在component中注入服务
import { Component } from '@angular/core';//引入服务import { RoutingService } from './services/routing.service';@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.css']})export class AppComponent {  //服务注入  constructor(    private routing:RoutingService  ) { }  title = 'app works!';}
step5:调用
<h1>  {{title}}</h1><a routerLink="component1">link-component1</a><!-- 直接调用服务的方法,而不是component.ts中的方法 --><button (click)="routing.showComponent()">click to component1</button><router-outlet></router-outlet>

效果和之前相同。

程序打包

使用angular-cli工具可以进行很方便的打包

  • ng build 打包的程序保留了ts脚本,在浏览器进行调试时十分方便。
  • ng build --prod 则将应用程序打包为生产环境部署的版本,仅留下混淆、压缩过的js文件,体积大大减小,应用启动也更为迅速。(在我的实际测试中,调试包为3.8兆时,生产包近1.1兆)

默认打包操作输出文件夹为src/dist。将其拷贝部署到web服务器即可。

0 0
原创粉丝点击