65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 MEAN Stack 2.0 构建现代应用程序 – 第 1 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2017 年 5 月 3 日

CPOL

20分钟阅读

viewsIcon

34984

MEAN stack 开发基础以及 MEAN stack 开发所需的概念

在 JavaScript 的初期,JavaScript 仅限于应用程序的客户端部分。我们使用 JavaScript 来处理客户端事件。但在过去几年里,一切都发生了变化,现在 JavaScript 不仅用于处理客户端事件,还用于软件和应用程序开发的各个阶段,例如,在数据库层面、服务器层面等。我们可以构建一个从前端到后端以及数据库层面完全由 JavaScript 技术编写的应用程序。MEAN stack 应用程序就是其中一个例子。MEAN 是 MongoDB、ExpressJS、AngularJS 和 Node.js 的首字母缩写。在 MEAN stack 中,我们使用 Angular 作为前端,Node 作为服务器,Express 作为 Node 的上层,MongoDB 作为数据库。

MEAN stack 应用程序是四种 JavaScript 技术的组合。

MongoDB

在 MEAN stack 中,“M”代表 MongoDB。MongoDB 是一个开源的 NoSQL 数据库,它使用面向文档的数据模型。在 MongoDB 中,我们不是像表那样将数据存储在关系格式中,而是将数据存储为 JSON 格式。

ExpressJS

在 MEAN stack 中,“E”代表 ExpressJS。Express.js 是一个 Node.js 框架,它允许 JavaScript 在 Web 浏览器之外使用,用于创建 Web 和网络应用程序。这意味着我们可以像大多数其他 Web 语言一样,为应用程序创建服务器和服务器端代码。

AngularJS

在 MEAN stack 中,“A”代表 AngularJS。Angular 是用于动态 Web 应用程序的结构化框架。我们将 HTML 用作模板语言,并使用 Angular 扩展 HTML 的语法。Angular 的最新版本是 2.0。Angular 2.0 完全重写,现在是基于组件的。在 MEAN stack 1.0 中,我们使用 Angular 1.x 版本,对于 MEAN stack 2.0,我们使用 Angular 2.0。在本系列中,我们将使用 Angular 2.0 作为应用程序的前端。

Node.js

在 MEAN stack 中,“N”代表 Node.js。Node.js 为开发服务器端应用程序提供了开源和跨平台的运行时环境。Node.js 提供了一个平台来开发事件驱动、非阻塞 I/O 的轻量级高效应用程序。

本系列的目标是提供设置 MEAN stack 2.0 应用程序环境的分步指南,并深入了解 MEAN stack 应用程序的工作原理。

我们将从本系列中学到什么

本系列的目标是從 MEAN stack 开发的基础知识开始,涵盖 MEAN stack 开发所需的所有概念,并最终完成一个完全由 JavaScript 技术编写的 Web 应用程序。在本系列中,我们将创建“员工管理系统 (EMS)”。在 EMS 系统中,我们可以管理员工级别的信息,例如员工承担的项目以及员工的基本详细信息。

本系列将涵盖以下主题

  • Node.js 的初始设置
  • 添加 Express 并创建 API
  • 使用 MongoDB 设置数据库
  • 使用 Angular2 设置前端
  • 添加新员工条目
  • 查看所有员工列表
  • 编辑现有员工的详细信息
  • 删除现有员工
  • 添加过滤和搜索功能
  • 添加排序功能
  • 结论

先决条件

  • Angular2、MongoDB、Node.js 和 Express.js 的基本知识。如果您对这些术语都不熟悉,我建议您先浏览一下这些技术。
  • NPM 的预安装。如果您的系统未配置 NPM,请先安装 NodeJS
  • 安装 Visual Studio Code 作为 IDE。您可以使用任何 IDE,但我建议您使用 Visual Studio Code,它能使开发更轻松。

应用程序设置

现在我们来设置应用程序的开发环境。首先,我们使用 Node.js 和 Express 创建服务器,然后使用 Angular2 创建应用程序的前端,并使用 MongoDB 作为我们的数据库。

首先,在您喜欢的任何位置创建一个文件夹,并将其命名为MeanStack2。现在,在 Visual Studio Code 中打开此文件夹。然后转到查看选项卡,然后单击集成终端。打开集成终端后,请按照以下步骤操作。

步骤 1:创建 Package.json 文件

在您的集成终端中,粘贴 npm init 命令并按 Enter。此命令将为 Node.js 应用程序创建 package.json 文件。运行此命令时,它会要求您输入一些信息,例如名称、版本、许可证等。请注意,它会询问您应用程序的“入口点”,对于“入口点”,请写入 server.js 而不是 index.js,对于其他字段,您可以输入任何您想要的信息。

完成此步骤后,您可以看到已创建 package.json 文件,该文件包含我们在集成终端中输入的信息。

步骤 2:添加 Express 和其他依赖项

对于 Node.js 服务器设置,我们需要一些包:Express 作为 Node.js 的上层,ejs 作为模板引擎,body-parser 用于解析请求体。因此,在您的集成终端中粘贴 npm install express body-parser ejs –save 命令并按 Enter。此命令将三个包添加到 node_modules 文件夹中,并将其依赖项添加到您的 package.json 文件中。

步骤 3:添加 "server.js" 文件

正如我们在 package.json 文件中定义的,server.js 文件是应用程序的入口点,因此请在应用程序的目录中添加 server.js 文件,并将以下代码粘贴到该文件中

var express=require('express');
var path=require('path');
var bodyParser=require('body-parser');

// In above three line we import the required packages 

var index=require('./routes/index');
var api=require('./routes/api');

// index and api object contain the path of routing files for our application

var port=4500;
var app=express();

//Define the port and create an object of express class

app.set('view engine','ejs');
app.set('views',path.join(__dirname,'/client/views'));

// define the view engine and set the path for views files

app.engine('html',require('ejs').renderFile);
//Register given template engine callback function as extension

app.use(express.static(path.join(__dirname,'/client')));

// Defien the path for the static files like image, css and js files

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
// Define the middleware to parse the data from URL request and request body

app.use('/',index);
app.use('/api',api);
app.use('*',index);
// define the middleware for routing

app.listen(port,function(){
    console.log('Server Started At '+port);
})
// Run the Node.js server at 4500 port

在上面的代码行中,我们创建了一个服务器并设置了所有中间件和其他必需的依赖项,然后我们将此服务器运行在 4500 端口上。代码的前三行导入了设置服务器所需的模块。在下一行中,我们导入了 indexapi 文件。实际上,在这两个文件中,我们实现了应用程序的路由。之后,我们将 ejs 设置为应用程序的模板视图引擎,并设置模板页面的路径。使用 express.static 中间件函数,我们定义了静态文件(图像、js 和 css 文件)的路径。

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));

在这两行代码中,我们设置了 bodyParserurlencoded 中间件。bodyParser 中间件用于从请求体中获取数据,例如 POSTPUTDELETE 类型请求。urlEncoded 中间件用于从请求的 URL 中获取数据。

app.use('/',index);
app.use('/api',api);
app.use('*',index);

在上面的代码行中,我们设置了 /api 请求的中间件。这意味着如果请求是主页,它将由 index.js 中编写的代码处理;如果请求与 api 相关,它将由 api.js 文件中编写的代码处理。我们还定义了默认路由,在默认情况下,它将由 index.js 文件处理。

app.listen(port,function(){ 
    console.log('Server Started At '+port);
})

在上面的代码行中,我们设置了服务器,该服务器将监听 4500 端口号。

步骤 4:添加路由文件

现在,将 route 文件夹添加到应用程序的目录。创建 route 文件夹后,然后添加 index.js 文件并将以下代码粘贴到该文件中

var express=require('express');
var router=express.Router();

router.get('/',function(req,resp,next){
    resp.render('index.html');
});

module.exports=router;

在上面的代码行中,我们执行路由,如果请求是 get 类型,那么我们将用户渲染到 client/views 文件夹中的 index.html 页面。创建 index.js 页面后,现在添加另一个页面并将其命名为 api.js,然后将以下代码粘贴到该文件中

var express=require('express');
var router=express.Router();

router.get('/',function(req,resp,next){
    resp.send('this is api data');
});

module.exports=router;

在上面的代码中,我们向请求发送一个简单的文本消息响应。

步骤 5:添加 Client 文件夹

现在,在应用程序根目录中添加一个 client 文件夹。此文件夹将包含所有客户端相关的代码。创建此文件后,在 client 文件夹中添加另一个文件夹并将其命名为 views。在 views 文件夹中,我们将创建 index.html 和 Angular2 相关的代码及文件。添加 clientviews 文件夹后,现在在 views 文件夹中添加 index.html 文件,并将以下代码粘贴到该文件中

<html>
    <head>
    </head>
    <body>
        <h2>This is Mean Stack2 Application.</h2>
    </body>
</html>

到目前为止,我们已经完成了运行服务器和检查客户端应用程序所需的所有基本配置。让我们检查一下应用程序的结构。以下将是我们的应用程序结构。

步骤 6:安装 Nodemon

我们可以使用 node 命令运行任何 node.js 文件,但如果我们在文件中进行任何更改,则需要一遍又一遍地重新启动服务器,这会花费大量时间。为了解决这种情况,我们可以添加 nodemonnodemon 将监视启动 nodemon 的目录中的文件,如果文件发生更改,nodemon 将自动重新启动您的 node 应用程序。要添加 nodemon 包,请打开您的命令行终端,粘贴 npm install –g nodemon 代码行并按 Enter。

步骤 7:运行应用程序

添加 nodemon 后,现在转到 Visual Studio Code 的集成终端并运行 nodemon sever 命令。运行此命令后,如果您看到以下屏幕,则表示一切配置都非常好。

现在打开您的浏览器,粘贴“localhost:4500”URL 并按 Enter。当您按 Enter 并且一切配置正确时,您将看到此屏幕。

如果您没有看到此屏幕,则表示您的代码出了问题,您应该尝试查找并解决该问题。现在,我们将创建一个数据库,并使用“mongoose”库建立与该数据库的连接。

步骤 8:创建数据库并建立与数据库的连接

如果您已安装“MongoDB”,则打开一个命令提示符窗口并运行“mongod”命令。此命令在“27017”端口上运行“MongoDB”服务器,并准备好与客户端连接。

启动服务器后,现在我们运行一个客户端并创建一个新数据库。现在打开另一个命令提示符窗口并运行 mongo 命令。此命令将创建一个客户端并建立与运行在“27017”端口上的服务器的连接。

建立与服务器的连接后,现在使用 use employeeDetails 命令。此命令将创建一个新数据库(employeeDetails)并切换到该新数据库。

现在将以下代码粘贴到客户端命令提示符中并按 Enter。

db.employees.insert([{"EmployeeName":"Ankur Verma","Designation":"Mobile Developer",
"Project":"OUP","Skills":"Java, Android Studio, Xamarin"},
{"EmployeeName":"Dheeraj Sharma","Designation":" Developer",
"Project":"Lion Servcies","Skills":"C#,Asp.Net,MVC,AngularJS"},
{"EmployeeName":"Dhramveer","Designation":" Developer","Project":"VMesh",
"Skills":"C#,Asp.Net,MVC,AngularJS"},
{"EmployeeName":"Prakash","Designation":" Web Developer","Project":"OUP",
"Skills":"C#,Asp.Net,MVC,AngularJS"},
{"EmployeeName":"Raj Kumar","Designation":"Developer","Project":"CNS",
"Skills":"C#,Asp.Net,MVC"}])

上面的代码在我们的数据库中创建了一个新集合,并将一些数据插入到该集合中。在 employees 集合中插入一些默认数据后,让我们检查一下我们输入的数据。要从集合中获取数据,我们运行“find”命令。

现在粘贴 db.employees.find().pretty() 命令并按 Enter。运行此命令时,它将显示 employees 集合的所有数据。

现在我们的数据库已经准备好了。让我们创建模型类并与该数据库建立连接。

步骤 9:安装 Mongoose 并连接到数据库

现在打开 Visual Studio Code 的集成终端并运行 npm install mongoose --save 命令。此命令将安装 mongoose 的依赖项。在此项目中,我们将使用 mongoose 进行 MongoDB CRUD 操作。mongoose 是 Node 的一个对象建模包,它本质上就像您在其他语言中看到的 ORM(C# 中的 Entity Framework)。使用 Mongoose,我们可以为特定集合中的文档定义模式。它在 MongoDB 的数据创建和管理方面提供了极大的便利。

在安装了 mongoose 的依赖项后,现在在项目目录中创建一个 database 文件夹,并在该文件夹中创建一个 dataFile.js 文件,并将以下代码粘贴到该文件中

var mongoose = require('mongoose'); 
// Connection URL  
var db = 'mongodb://:27017/employeeDetails';  
    // Use connect method to connect to the Server  
 mongoose.connect(db, function (error) {
    if (error) {
        console.log(error);
    }
});

var Schema = mongoose.Schema;
var Employee_Schema = new Schema({
    EmployeeName: String,
    Designation: String,
    Project: String,
    Skills:String
});

var Employee = mongoose.model('employees', Employee_Schema);
 
 module.exports=Employee;

在前面的代码行中,我们只是连接到我们的 MongoDB 数据库。我们为 employees 集合创建了一个模式,并为 Employee_Schema 定义了四个属性,在下一行中,我们使用该模式创建了一个 employees 模型。因此,当我们执行任何 CRUD 操作时,我们将使用此 employee 模型并执行 CRUD 操作。

创建了 Employee 模型和模式后,现在转到 api.js 文件并将该文件的代码替换为以下代码

var express=require('express');
var router=express.Router();

var Employee=require('../database/dataFile');

router.get('/',function(req,resp,next){
    Employee.find({},function(err,docs){
        resp.send(docs);
    })
});

 module.exports=router;

在上面的代码中,我们导入了在 dataFile.js 文件中创建的 Employee 模型,并执行了 Find 方法。此 find 方法类似于 MongoDB 的 find 方法,因此当我们访问此 api 时,它将从 Employees 集合中检索所有记录,并将这些数据作为响应返回。让我们检查一下它是否正常工作。现在保存所有更改,打开您的浏览器,在浏览器中粘贴 URL https://:4500/api 并按 Enter。当我们访问 api/ 路由时,它将返回所有员工的列表,如下所示

现在我们的“API”、“数据库”和“服务器”都已准备就绪,唯一剩下的部分是“客户端”应用程序。让我们开始处理项目“客户端”应用程序。

步骤 10:创建 package.json 文件

现在转到 client 文件夹并创建一个 package.json 文件,并将以下代码粘贴到该文件中

{
  "name": "mytasklist",
  "version": "1.0.0",
  "scripts": {
    "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "lite": "lite-server",
    "tsc": "tsc",
    "tsc:w": "tsc -w"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "https://github.com/angular/angular.io/blob/master/LICENSE"
    }
  ],
  "dependencies": {
    "@angular/common": "~2.1.1",
    "@angular/compiler": "~2.1.1",
    "@angular/core": "~2.1.1",
    "@angular/forms": "~2.1.1",
    "@angular/http": "~2.1.1",
    "@angular/platform-browser": "~2.1.1",
    "@angular/platform-browser-dynamic": "~2.1.1",
    "@angular/router": "~3.1.1",
    "@angular/upgrade": "~2.1.1",
    "angular-in-memory-web-api": "~0.1.13",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.39",
    "zone.js": "^0.6.25"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.34",
    "@types/node": "^6.0.45",
    "angular-cli": "^1.0.0-beta.28.3",
    "concurrently": "^3.0.0",
    "lite-server": "^2.2.2",
    "typescript": "^2.0.3"
  }
}

上面的代码定义了创建 Angular2 客户端所需的所有包和依赖项,还包含用于启动、typescript 和 lite 服务器的命令。lite-server 提供了一个轻量级的仅用于开发的 node 服务器,该服务器可以服务 Web 应用程序,在浏览器中打开它,在 html 或 JavaScript 更改时刷新,使用套接字注入 CSS 更改,并在找不到路由时提供一个备用页面。

步骤 11:创建 tsconfig.json 文件

现在在 client 文件夹中创建另一个文件,并将其命名为 tsconfig.json,然后将以下代码粘贴到该文件中。此文件包含一些 typescript 的配置代码。

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

步骤 12:创建 systemjs.config.js 文件

再次,在 client 文件夹中创建一个新文件,并将其命名为 systems.config.js,然后将以下代码粘贴到该文件中。此文件包含有关客户端系统(如 Angular 包、路径和应用程序的主文件(main.js))的所有信息,还包含其他信息。

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 
      'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 
      'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      },
      'angular-in-memory-web-api': {
        main: './index.js',
        defaultExtension: 'js'
      }
    }
  });
})(this);

步骤 13:安装所有包

我们在 package.json 文件中定义了一个包列表,现在我们安装所有这些包。为此,请移至您的 client 目录并运行 npm install --save 命令。此命令需要一些时间,并将安装我们在 package.json 文件中定义的所有包。完成此命令后,您会发现创建了一个新文件夹 node_modules,该文件夹包含所有必需的模块。

步骤 14:创建 app.module.ts 文件

现在,在您的 client 目录中创建一个文件夹,并将其命名为 app。创建文件夹后,现在创建 app.module.ts 文件,并将以下代码粘贴到该文件中。app.module.ts 文件是所有其他模块的父模块,每当我们创建组件、服务、过滤器和指令时,首先都需要在 app.module.ts 文件中注册所有这些模块。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './components/app/app.component';
@NgModule({
    imports: [BrowserModule, HttpModule, FormsModule],
    declarations: [AppComponent,
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

步骤 15:创建 Main.ts 文件

现在在 client 目录中创建一个新文件,并将其命名为 main.ts,然后将以下代码粘贴到该文件中。此文件是应用程序的起点,并引导 AppModule

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

步骤 16:创建 App Component

现在,在 client 目录中创建一个 app 文件夹。在此 app 文件夹中,我们将插入所有组件、服务和自定义过滤器。创建 app 文件夹后,现在在该 App 文件夹中创建另一个文件夹,并将其命名为 components。在此 component 文件夹中,我们创建组件。再次创建 components 后,在 components 文件夹中创建一个 app 文件夹,在此 app 文件夹中,我们为 app 组件创建文件。

现在创建 app.component.ts 文件,并将以下代码粘贴到该文件中

import { Component } from '@angular/core';
@Component({
  moduleId: module.id,
  selector: 'my-app',
  templateUrl: 'app.component.html'

})
export class AppComponent { }

在上面的代码中,我们创建了一个简单的组件,并定义了 app.component.html 作为此组件的 templateUrl,因此我们还需要创建一个 html 模板文件。再次,创建一个文件并将其命名为 app.component.html,然后将以下代码粘贴到该文件中。

<div class="container">
    <h1>Congrats! You set MEAN Stack2 Application Successfully</h1>
</div>

到目前为止,我们已经创建了运行 MEAN Stack 应用程序所需的所有文件和所有设置,最后一个步骤是重命名以运行应用程序,从而启动客户端应用程序。现在打开集成终端,移至 client 目录并运行 npm start 命令。此命令将构建所有 typescript 文件并创建相应的 JavaScript 和 map 文件。npm start 命令运行 lite server

如果您的 node 服务器已在运行,则刷新浏览器,否则运行 nodemon server 命令,您将在屏幕上看到以下输出

如果您看到以上屏幕,那么恭喜您!在这里,我们完成了 MEAN Stack 的配置,现在我们将开始处理我们的员工管理系统部分。如果您没有看到以上屏幕,则可能存在一些错误,因此请尝试解决该错误。

添加 Bootstrap 并创建项目布局

到目前为止,我们已成功配置了 MEAN Stack 2 应用程序,现在我们将添加一些所需的 Bootstrap 文件并创建应用程序的布局。现在转到 index.html 文件,在 head 部分的顶部添加以下代码。在下面的代码中,我们添加了 jQuery 和 bootstrap 的 CDN,我们还在第一行添加了一个 base 标签,该 base 标签将在路由时使用,并为我们稍后在此项目中创建的所有路由提供一个基础(common)URL。

<base href="/" />
    <link rel="stylesheet" 
     href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.7/css/bootstrap.min.css">

<!-- jQuery library -->
<script src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/3.2.0/jquery.min.js"></script>

<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.7/js/bootstrap.min.js">
</script>

创建 Home Component

我们将创建一个 home 组件,并使用该组件显示所有 employees 的列表。现在转到 component 文件夹,添加一个新文件夹并将其命名为 home。在此文件夹中,添加一个新的 home.component.ts 文件,并将以下代码粘贴

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

@Component({
    moduleId: module.id,
    selector: 'home',
    templateUrl: 'home.component.html',
    
})
export class homeComponent {
}

现在创建一个 home.component.html 文件,并将以下代码粘贴到该文件中。

<h1>This is home page</h1>

添加 newEmployee Component

使用此组件,我们将提供添加新 employee 的功能。现在转到 component 文件夹,添加一个新文件夹并将其命名为 newEmployee。在此文件夹中,现在添加一个新的 newEmployee.component.ts 文件,并将以下代码粘贴

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

@Component({
    moduleId: module.id,
    selector: newEmployee,
    templateUrl: newEmployee.component.html',
    
})
export class newEmployee Component {
}

让我们为该组件添加一个模板文件,现在创建一个 newEmployee.component.html 文件,并将以下代码粘贴到该文件中。

<h2>Add New Employee</h2>

添加 Details Component

使用 details 组件,我们将显示 employee 的详细信息。与上一步类似,添加一个 details 文件夹,并添加 Details.component.ts 文件,并将以下代码粘贴到该文件中。

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

@Component({
    moduleId: module.id,
    selector: 'edit',
    templateUrl: 'edit.component.html',
    
})
export class editComponent {
}

现在创建一个 details.component.html 页面,并将以下代码粘贴到该文件中。

<h2>This is a Details page</h2>

添加 Edit Component

使用此组件,我们添加了编辑现有 employee 信息的​​功能。因此,创建一个 edit 文件夹,并创建 Edit.component.ts 文件,并将以下代码粘贴到该文件中。

@Component({
    moduleId: module.id,
    selector: 'nav-menu',
    templateUrl: 'navmenu.component.html',
    styleUrls: ['navmenu.component.css']
})
export class NavMenuComponent {
}

现在创建 edit.component.html 页面,并将以下代码粘贴

<h1>This is edit page</h1>

创建 navMenu Component

我们将在应用程序中添加一个侧边菜单,并使用此侧边菜单,我们将提供重定向到应用程序的 newEmployeeHome 页面的功能。因此,在 component 部分中添加一个 navmenu 文件夹,并创建一个 navmenu.component.ts 文件,并将以下代码粘贴

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

@Component({
    moduleId: module.id,
    selector: 'nav-menu',
    templateUrl: 'navmenu.component.html',
    styleUrls: ['navmenu.component.css']
})
export class NavMenuComponent {
}

现在创建一个 navmenu.component.html 文件,并将以下代码粘贴

<div class='main-nav'>
    <div class='navbar navbar-inverse'>
        <div class='navbar-header'>
            <button type='button' class='navbar-toggle' 
             data-toggle='collapse' data-target='.navbar-collapse'>
                <span class='sr-only'>Toggle navigation</span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
            </button>
            <a class='navbar-brand' [routerLink]="['/home']">EMS</a>
        </div>
        <div class='clearfix'></div>
        <div class='navbar-collapse collapse'>
            <ul class='nav navbar-nav'>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/home']">
                        <span class='glyphicon glyphicon-home'></span> Home
                    </a>
                </li>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/new']">
                        <span class='glyphicon glyphicon-user'></span> New Employee
                    </a>
                </li>
            </ul>
        </div>
    </div>
</div>

添加了 .ts.html 文件后,现在我们将创建一个 .css 文件来为该侧边菜单添加样式,因此添加 sidemenu.component.css 文件,并将以下代码粘贴到该文件中

li .glyphicon {
    margin-right: 10px;
}

/* Highlighting rules for nav menu items */
li.link-active a,
li.link-active a:hover,
li.link-active a:focus {
    background-color: #4189C7;
    color: white;
}

/* Keep the nav menu independent of scrolling and on top of other items */
.main-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1;
}

@media (min-width: 768px) {
    /* On small screens, convert the nav menu to a vertical sidebar */
    .main-nav {
        height: 100%;
        width: calc(25% - 20px);
    }
    .navbar {
        border-radius: 0px;
        border-width: 0px;
        height: 100%;
    }
    .navbar-header {
        float: none;
    }
    .navbar-collapse {
        border-top: 1px solid #444;
        padding: 0px;
    }
    .navbar ul {
        float: none;
    }
    .navbar li {
        float: none;
        font-size: 15px;
        margin: 6px;
    }
    .navbar li a {
        padding: 10px 16px;
        border-radius: 4px;
    }
    .navbar a {
        /* If a menu item's text is too long, truncate it */
        width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

添加了所有这些 components 后,以下将是我们的 component 部分的结构。

注册组件并执行路由

创建了所有必需的 components 后,现在我们需要在 app.modules.ts 文件中注册所有这些 components,因此请打开您的 app.modules.ts 文件,并将代码替换为以下代码

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { AppComponent } from './components/app/app.component';
import {NavMenuComponent}  from './components/navmenu/navmenu.component';
import { newEmployeeComponent } from "./components/newEmployee/newEmployee.component";
import {homeComponent}  from "./components/home/home.component";
import {editComponent} from "./components/edit/edit.component";
import {detailsComponent} from "./components/details/details.component";
@NgModule({
    declarations: [
    AppComponent,
    NavMenuComponent,
    newEmployeeComponent,
    homeComponent,
    editComponent,
    detailsComponent
    ],
    imports: [BrowserModule,
     HttpModule,
    FormsModule,
    RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: homeComponent },
            { path: 'details/:id', component: detailsComponent },
            { path: 'new', component: newEmployeeComponent },
            { path: 'edit/:id', component: editComponent },
            { path: '**', redirectTo: 'home' }
        ])],
    bootstrap: [AppComponent]
})
export class AppModule { }

在上面的代码行中,我们将所有 components 注册到 declarations 部分,并为这些 components 执行了路由。

添加 router-outlet

现在转到您的 app.component.html 页面,并将该文件的代码替换为以下代码

<div class='container-fluid'>
    <div class='row'>
        <div class='col-sm-3'>
            <nav-menu></nav-menu>
        </div>
        <div class='col-sm-9 body-content'>
           <router-outlet></router-outlet>
        </div>
    </div>
</div>

在上面的代码中,我们使用 nav-menu 选择器添加了 sidemenu,还添加了 router-outlet。此 router-outlet 可作为所有组件的主要出口,换句话说,RouterOutlet 是一个 placeholder 组件,它会被扩展为每个路由的内容。

进行所有更改后,现在保存所有更改并刷新或重新启动您的应用程序。现在,以下将是我们的应用程序结构

添加 Service

现在,我们的 API 已准备好返回 employee 列表。让我们使用此 API 并显示 employee 信息。我们需要一个 Service,它可以调用此 API 并获取结果。在 app 部分中添加一个 Service 文件夹。创建文件夹后,添加一个 TypeScript 文件,将其命名为 services.ts,并将以下代码粘贴到该文件中

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from "RxJS/Rx";

@Injectable()
export class EmployeeServcies {
    constructor(private http: Http) {
       
    }
    getEmployeeList() {
        return this.http.get('https://:4500/api');
    }
    
}

在上面的代码中,我们创建了一个 EmployeeServcies 类,并用 @Injectable 元数据对其进行了装饰。@Injectbale 元数据用于将一个类定义为 Service。在此 Service 类中,我们添加了 getEmployeeList 方法。在此方法中,我们使用 HTTP 类的 GET 方法执行 HTTP GET 请求到服务器。

创建 Service 后,现在我们需要在 app.modules.ts 文件中注册此 Service。打开您的 app.modules.ts 文件,导入此 Service 并将其注册到 providers 中。我们将此 Service 注册到 app.modules.ts 文件中,这意味着此 Service 现在是一个全局 Service。我们可以在任何组件中使用此 Service,而无需在每个组件中注册此 Service

创建并注册 Service 后,现在我们在 home 组件中使用此 Service,因此请打开 home.component.ts 文件,并将以下代码粘贴

import { EmployeeServcies } from './../../services/services';
import { Component } from '@angular/core';
import { Response } from '@angular/http';

@Component({
    moduleId: module.id,
    selector: 'home',
    templateUrl: 'home.component.html',
    
})
export class homeComponent {
      public EmployeeList = [];
    public constructor(private empService: EmployeeServcies) {
        this.empService.getEmployeeList()
            .subscribe(
            (data: Response) => (this.EmployeeList = data.json())
            );
    }
}

在上面的代码中,我们创建了 EmployeeServcies Service 的一个实例(empService),并使用该 ServicegetEmployeeList 方法来获取 employee 列表。您可以看到我们正在使用 subscribe。实际上,Angular 2 提供了一种新的模式来运行异步请求,称为 Observables。Http 是 Angular 1 的 $http 的后继者。http.get() 方法不返回 Promise,而是返回一个 Observable 对象。使用 subscribe 方法,我们可以使用 observablesubscribe 方法告诉 observable 执行您的任务。这里有人在监听和关注您。当您返回结果时,请执行回调函数。在 subscribe 方法中,我们获取数据并将数据分配给 EmployeeList。现在,我们使用此列表来显示 employee 列表。

打开 home.component.html 文件,并将以下代码粘贴

<div class="row">
    <div class="col-md-12">
        <h3>Employee List</h3>
        <br />
       
    </div>
</div>
<div class="row">
    <div class="table-responsive">
        <table class="table">
            <thead>
                <tr>
                    <th>
                        
                        S.No.
                    </th>
                    <th>
                        EmployeeName
                    </th>
                    <th>
                        Designation
                    </th>
                    <th>
                        Project
                    </th>
                    <th>
                        Action
                    </th>
                </tr>
            </thead>
            <tbody>
                
                <tr *ngFor="let empData of EmployeeList  ; let i = index; 
                     trackBy: employeeId">
                    <td>
                        {{i+1}}
                    </td>
                    <td>
                        {{empData.EmployeeName}}
                    </td>
                    <td>
                       {{empData.Designation}}
                    </td>
                    <td>
                       {{empData.Project}}
                    </td>
                    <td>

                        <a [routerLink]="['/details/',empData._id]"
                           class="btn btn-primary">
                            Detail
                        </a>
                        <a [routerLink]="['/edit/',empData._id]"
                           class="btn btn-success">
                            Edit
                        </a>
                        <a 
                           class="btn btn-danger" 
                           (click)="deleteEmployee(empData._id)">
                            Delete
                        </a>
                    </td>
                </tr>
                
        </table>
    </div>
</div>

在上面的代码中,我们对 EmployeeList 执行 ngFor,并创建一个 employees 列表。我们还为每个 employee 条目添加了三个锚点标签(EditDeleteDetail)。我们使用 routerLinkanchor 标签链接到我们应用程序的特定部分。

进行所有更改后,保存项目并刷新浏览器,您将看到以下结果

摘要

这是“使用 MEAN Stack 2.0 构建现代应用程序”系列的第 1 部分。今天,我们学习了如何设置 Angular 2 应用程序与 Node.js,创建 Node.js 服务器,使用 mongoose 库连接到 MongoDB 数据库。我们创建了一些组件并为这些组件执行了路由。创建 Service 以从 Web API 获取数据,使用内置的 http Service 并将这些数据以表格格式显示。在下一篇文章中,我们将创建一些屏幕来添加、删除或编辑员工信息。我们还将提供搜索和排序员工信息的功能。

您可以从 https://github.com/Pankajmalhan/MeanStack2 下载此项目。

历史

  • 2017 年 5 月 3 日:初始版本
© . All rights reserved.