[基础系列] Angular2 快速入门

WOC,bate才不到一个月,原来写的快速入门已经行不通。比较大变化去了angular2字眼,可见正式更近了。

一、环境的先决条件

主要是两个工具:Node.js(5.x.x) 和 NPM(3.x.x),版本检查请自行 node -vnpm -v

当然作为一名天朝人,最好再安装一个 cnpm,这是良心淘宝的 NPM 镜像,再也不必担心下载不下来包包了。

在开始之前最好先安装几个全局包:

  • cnpm install typings -g
  • cnpm install lite-server -g

二、把示例运行起来

1、源代码

注:如果是Windows在使用CMD时一定要用管理员模式。

示例源代码已经部署在github上,所以我们只需要

git clone  https://github.com/angular/quickstart  my-proj
cd my-proj

当然默认是不包括 node_modules 文件夹,因此我们还需要使用cnpm安装模块。

cnpm install

目前用cnpm我没有遇到什么变态问题,如果你有遇到很奇怪的各种错误的话,尝试删除 node_modules 文件夹,然后改用 npm install 试试(记住CMD要管理员模式)。

2、运行

npm start

会自动通过浏览器打开 http://localhost:3000/,此时你可以修改 app/app.component.ts 里面的【My First Angular 2 App】字符串会自动重新编译并自动刷新浏览器(虽然它真的好慢),这一点就没有react+webpack的热替换牛B。

三、从零开始构建快速入门

系统环境:Win10。

1、开发环境

  • 安装 node & npm & cnpm
  • 创建项目文件夹和依赖包定义以及项目设置
  • 创建根组件
  • 添加 main.ts 引导Angular启动根组件
  • 添加 index.html 承载应用程序的网页
  • 构建运行应用

2、第一步:创建和配置项目

这一步需要三个步骤:

  • (a) 创建项目文件夹
  • (b) 添加依赖包定义和配置文件
  • (c) 安装包

(a) 创建项目文件夹

mkdir angular2-quickstart
cd    angular2-quickstart

(b) 添加依赖包定义和配置文件

在根目录添加以下几个配置文件:

package.json 列出 QuickStart 应用所需要的依赖包,以及一些用运行脚本命令。

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    // npm start:并行运行tsc:w&lite任务
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    // 启用静态服务器
    "lite": "lite-server",
    // 安装ts定义文件,postinstall是指当npm install后,所要运行的指令
    "postinstall": "typings install",
    // tsc:编译typescript
    "tsc": "tsc",
    // tsc -w:编译typescript并监听ts文件
    "tsc:w": "tsc -w",
    // 列出本地已经安装的typing文件
    "typings": "typings"
  },
  "license": "ISC",
  // 应用运行所需要的依赖包
  // 包不再出现 angular2 字眼,所以我们在import时都是用 `@angular/core`
  "dependencies": {
    "@angular/common":  "2.0.0-rc.1",
    "@angular/compiler":  "2.0.0-rc.1",
    "@angular/core":  "2.0.0-rc.1",
    "@angular/http":  "2.0.0-rc.1",
    "@angular/platform-browser":  "2.0.0-rc.1",
    "@angular/platform-browser-dynamic":  "2.0.0-rc.1",
    "@angular/router":  "2.0.0-rc.1",
    "@angular/router-deprecated":  "2.0.0-rc.1",
    "@angular/upgrade":  "2.0.0-rc.1",
    "systemjs": "0.19.27",
    "core-js": "^2.4.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "angular2-in-memory-web-api": "0.0.9",
    "bootstrap": "^3.3.6"
  },
  // 开发时所需要的依赖包
  "devDependencies": {
    "concurrently": "^2.0.0", // 用于并行运行多个任务
    "lite-server": "^2.2.0", // 静态文件服务器
    "typescript": "^1.8.10", // ts编译器
    "typings":"^0.8.1" // ts定义文件管理器
  }
}

tsconfig.json TypeScript编译器配置文件。

{
  "compilerOptions": {
    "target": "es5", // 指定生成后ES版本 
    "module": "commonjs", // 指定模块类型,这包括:commonjs、amd、system、umd、es2015
    "moduleResolution": "node", // 模块解析方式,node(也叫node.js)表示使用 import 或 export 来操作模块
    "sourceMap": true, // 是否生成sourceMap
    "emitDecoratorMetadata": true, // 支持带有装饰器的声明生成元数据
    "experimentalDecorators": true, // 支持注解
    "removeComments": false, // 移除注释
    "noImplicitAny": false // 当编译器不能根据变量的使用来推断变量类型时,直接默认为 any 类型
  },
  // 排除不编译的目录
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

以上我已经做了注释,点击解更多

typings.json TypeScript定义文件,目的就是为了对一些非Typescript编译器原生支持的定义做声明,ts的要求很严格,如果你使用编译器无法识别的定义会报错。

{
  "ambientDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160317120654",
    "jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
    "node": "registry:dt/node#4.0.0+20160509154515"
  }
}

注:ts编译器对于重复定义也会报错,因此,可以在 tsconfig.json 中指定要排除的文件。

systemjs.config.js SystemJS配置文件。

/**
 * SystemJS配置文件
 */
(function(global) {
  // 别名映射表,告诉System加载器从哪找文件
  var map = {
    'app':                        'app', // 'dist',
    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs'
  };
  // 告诉System加载器如何加载模块
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' },
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Add package entries for angular packages
  ngPackageNames.forEach(function(pkgName) {
    packages['@angular/'+pkgName] = { main: pkgName + '.umd.js', defaultExtension: 'js' };
  });
  var config = {
    map: map,
    packages: packages
  }
  System.config(config);
})(this);

(c) 安装包

cnpm install

3、第二步:Angular组件

在根目录下创建 app 文件夹用来保存应用代码。

mkdir app

并添加 app.component.ts 文件,内容为:

import { Component } from '@angular/core';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})

export class AppComponent {}

注:我建议用VS CODE来写代码,因为对比下来,就它智能提醒最棒。

AppComponent作为根组件

Angular2是以组件为中心,我们构建的整体应用都是由一个复杂的组件树构成的。按惯例性,最好都有一个名为 AppComponent 组件做为根组件。示例中的代码非常简单组件,但确承载着一个组件最基本的组成要素:

  • 使用 import 语法导入我们需要的引用库。
  • @Component 装饰器告诉Angular如何创建并渲染组件。
  • 组件类用来控制模板的外观和行为能力。

import

Angular是一个模块化应用程序(包括Angular框架自身),由许多文件组成,每一个文件的目的性非常强。比如我们需要 @Component 装饰器,我们可以从 Angular Core 模块中获取。

import { Component } from '@angular/core';

也许你会有些疑惑,因为我们刚说是一切都是文件,按理 ./app.component 之类的来加载某个模块,这其实是因为angular的对框架自身的特殊照顾,使用的是模块ID来降低庞大的core模块的认知成本。

@Component decorator

Component 是一个装饰功能,需要一个元数据对象作为参数,并使用 @ 前缀符号调用它,这其实是TypeScript的语法。

@Component({
  selector: 'my-app',
  template: '<h1>My First Angular 2 App</h1>'
})

参数中包括两个最常用的属性 selectortemplate

selector 指定一个CSS选择器,示例中Angular会去查找文档中带有 <my-app> 元素。

template 指定组件模板,告诉组件如何渲染的,示例是输出一个 h1 标签。

组件类

示例最底部是一个名为 AppComponent 的空类,也是我们业务逻辑编写的地方。 export 它和前面的 import 其实是相对应的,是模块化中最核心的两个概念,前者是指定模块的对外接口是什么;后者是加载模块相应的接口某个功能。

有关组件的更多细节内容请看【Angular2 官网文章阅读指南】(会努力尽可能更新最新变动)。

4、第三步:添加 main.ts

现在已经有根组件,接着创建一个 app/main.ts 用来引导Angular启动,并默认加载该组件。

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';

bootstrap(AppComponent);

引导启动

注意这里是从 @angular/platform-browser-dynamic 载入 bootstrap 的,而不是 @angular/core,这是因为Angular可以多种方式来启动,比如:Web、Apache Cordova、NativeScript、以及听说还在搞的Angular转IOS或Angular也说不定。

5、第四步:添加 index.html

在项目根目录下创建一个 index.html HTML文件,毕竟我们现在还是在浏览器中运行Angular程序。

<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">
    <!-- 1. Load libraries -->
     <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </head>
  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

HTML有几处需要注意:

  1. JavaScript库。
  2. SystemJS配置文件。
  3. <my-app> 标签。

脚本库

     <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>

和之前相比,这里已经看不到任何有关Angular库引用了。只保留了一些ES6所需要的库。

SystemJS

快速入门依然还是使用SystemJS来加载用户程序和模块,前面已经在根目录下添加过 systemjs.config.js 文件。

其实SystemJS更适合用于教学,官方特别说明SystemJS只是一个选择而已,可能估计很多人和我一样挺反对用SystemJS来做为快速入门的开始。

有关SystemJS配置,前面已经有注释,就不再赘述。

样式

最后添加一些样式美化一个HELLO WORLD吧。

h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}
body {
  margin: 2em;
}

 /*
  * See https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css
  * for the full set of master styles used by the documentation samples
  */

6、第五步:运行起来

npm start

7 Comments

  1. 现在rc版本了,请问博主会更新么

  2. 不错的使用入门解说

  3. linesk@163.com

    2016年6月17日 at 09:25

    请问 login 和 home 的 ui差距比较大 如何解决啊
    不知道单页模式下 该如何弄

    • asdf

      2016年7月5日 at 12:19

      我之前也遇到过,但出于Ng2以组件树为基准,也没有找到一个很合理的解决办法;后来我干脆直接打开新窗体。

  4. 请问 我有
    NavComponent
    里面有一个 sidebarOpen

    我需要在 HomeComponent 里面要使用 sidebarOpen 这个属性
    该如何共享 我是用该属性来 空值 home。html里面的class
    这个值的 修改是在 NavComponent

    • asdf

      2016年7月5日 at 12:24

      方法很多,无非就是离开这两种办法:
      1、利用Service作为中间件来传递数据。
      2、利用事件来通知,但必须有个前提条件,那就是HomeComponent组件是在NavComponent下面。此时;可以利用事件来解决。

发表评论

Your email address will not be published.

*

© 2017 卡片机色彩 沪ICP备13032872号-3

Theme by cipchk

to top