Angular2 单页应用的编写 by 嗡
来源:互联网 发布:数据铁笼技术方案 编辑:程序博客网 时间:2024/05/29 03:19
- 单页应用的特点
- 优势
- 劣势
- 程序编写
- 开发环境
- 新建项目
- 主要概念
- Component
- componentts
- componenthtml
- componentts和componenthtml的关联和绑定数据和行为
- 路由
- 路由的声明
- 路由实例
- 服务
- 实例将路由跳转封装为服务
- step1 建立服务
- step2实现服务方法
- step3在appmodulets中引入服务
- step4在component中注入服务
- step5调用
- 实例将路由跳转封装为服务
- Component
- 程序打包
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服务器即可。
- Angular2 单页应用的编写 by 嗡
- 嗡汤圆的Angular2 单页应用一些优化总结
- 编写你的第一个Angular2 Web应用
- 单例的编写
- group by 的应用
- CONNECT BY 的应用
- connect by的应用
- 使用Angular2及WebApi开发SPA类型的企业应用
- 使用Angular2及WebApi开发SPA类型的企业应用
- 使用Redux和ngrx构建更好的Angular2应用(一)
- 使用Redux和ngrx构建更好的Angular2应用(二)
- 使用Redux和ngrx构建更好的Angular2应用(三)
- 使用Redux和ngrx构建更好的Angular2应用(四)
- Angular2上应用基于jQuery的Bootstrap 3
- RxJS核心概念之Subjet在angular2+上的应用
- 由单页应用引出的胡言乱语
- 基于react-router的单页应用
- 如何提升单页应用的体验
- 【算法】不能被素数相加得到的偶数
- .Net程序员学用Oracle系列(16):访问数据库(ODP.NET)
- Docker Dockerfile详解
- Android创建并更新通知栏通知
- [HDU 1116]Play on Words(欧拉回路/欧拉路径+并查集)
- Angular2 单页应用的编写 by 嗡
- Oracle Data Guard 主库 归档文件 删除策略
- Navicat 创建数据库和表之使用命令创建
- 冒泡排序
- Java设计模式学习(3)- Chain Of Responsibility模式 (上)
- HDU 2601 An easy problem (数论)
- 慧眼云:基于云计算和大数据分析的主动防御实践
- abp及实战框架概述
- 20170219am js