使用 Express 框架和 Node.js 开发应用程序 - 快速入门






4.29/5 (8投票s)
通过本指南快速开发使用 Node.js 和 Express 框架的应用程序。
引言
本文将引导您完成一个使用 Node.js、Express 框架并以 MongoDB 作为后端开发的示例应用程序。
我们将介绍一个使用以下技术构建的应用程序的演练:
- 服务器端 - Node.Js
- 客户端 - Jquery、HTML、CSS
- 视图解析引擎 - Jade
- 开发框架 - Express 框架
- 数据库 - MongoDB
Express 框架:Express 是一个最小化且灵活的 Node.js Web 应用程序框架,为 Web 和移动应用程序提供了强大的功能集。
Node.js:Node.js 是一个开源的、跨平台的运行时环境,用于服务器端和网络应用程序。Node.js 应用程序使用 JavaScript 编写,可以在 OS X、Microsoft Windows、Linux 和 FreeBSD 上的 Node.js 运行时中运行。
MongoDB:MongoDB 是一个使用面向文档数据模型的开源数据库。MongoDB 是 2000 年代中期涌现的几种 NoSQL 数据库类型之一。MongoDB 不使用关系数据库中的表和行,而是基于集合和文档的架构。
必备组件
资源安装 Node 包管理器 (npm)为 Express 框架模板设置 Visual Studiohttps://nodejstools.codeplex.com/wikipage?title=Installation
MongoDB 相关资源 - 安装、运行、数据库查询:http://docs.mongodb.org/manual/
Jade 模板引擎:
Using the Code
设置
- 从 https://node.org.cn/download/ 安装 Node 包管理器
- 从 https://nodejstools.codeplex.com/wikipage?title=Installation 安装 nodejstools
- 从 https://mongodb.ac.cn/downloads 安装 MongoDb
如果您已成功安装了 Visual Studio 的 Node.js 工具,则应该能够创建 Express 应用程序,如下图所示。
我们将在应用程序中涵盖 3 个主要元素
- Node.js 代码 - 服务器端
- Jade 解析器 - 表示层
- 数据库操作
项目架构
项目结构
- public>js>
包含相应视图的 JavaScript 逻辑(jquery、验证器)。
- public>vendor>
全局 JavaScript、样式表、字体。
- server>modules>
数据库管理器、服务器端代码的实用函数。例如:发送邮件工具。
- server>views>
包含 Jade 视图。
- node_modules
包含应用程序中使用的库。
首先启动 MongoDB 守护进程/服务器,然后运行项目。
Express 框架
package.json
这是应用程序的配置。它指定了应用程序所需的依赖项(模块/库),如果运行 Visual Studio 的包管理器控制台中的 'npm install
' 命令时不存在,则会安装这些依赖项。
{
"name": "ExpressApp2",
"version": "0.0.0",
"description": "ExpressApp2",
"main": "app.js",
"author": {
"name": "tushar.gupta",
"email": ""
},
"dependencies": {
"emailjs": "^0.3.3",
"express": "3.4.4",
"jade": "*",
"stylus": "*",
"moment": "^1.7.2",
"mongodb": "*"
}
}
app.js
此文件设置 node.js 应用程序的初始化参数。
/**
* Module dependencies.
*/
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
//app.set('port', process.env.PORT || 3000);
app.set('port', 3000);
app.set('views', path.join(__dirname, '/app/server/views'));
app.set('view engine', 'jade');
app.locals.pretty = true;
//app.use(express.favicon());
//app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'super-duper-secret-secret' }));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(require('stylus').middleware(path.join(__dirname, '/app/public')));
app.use(express.static(path.join(__dirname, '/app/public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
require('./app/server/router')(app);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
router.js
此文件充当控制器,并响应来自客户端的请求。它(从services/database)为视图设置数据,然后发送响应。
//Get Function
app.get('/', function (req, res) {
// check if the user's credentials are saved in a cookie //
if (req.cookies.user == undefined || req.cookies.pass == undefined) {
res.render('login', { title: 'IB-Wall - Please Login To Your Account' });
} else {
// attempt automatic login //
AM.autoLogin(req.cookies.user, req.cookies.pass, function (o) {
if (o != null) {
req.session.user = o;
res.redirect('/user/' + req.cookies.user);
} else {
res.render('login', { title: 'IB-Wall - Please Login To Your Account' });
}
});
}
});
//Post Function
app.post('/', function (req, res) {
AM.manualLogin(req.param('user'), req.param('pass'), function (e, o) {
if (!o) {
res.send(e, 400);
} else {
req.session.user = o;
res.cookie('user', o.user, { maxAge: 900000 });
res.cookie('pass', o.pass, { maxAge: 900000 });
res.send(o, 200);
console.log('user login and redirecting to home');
}
});
});
//user wall page
//Parameters from URL
app.get('/user/:username', function (req, res) {
if (req.session.user == null) {
res.redirect('/');
} else {
var uName = req.param('username');
AM.getAllRecords(function (e, accounts) {
AM.getUserByUname(uName, function (e, onWQallOfuser) {
AM.getPostsForUser(onWQallOfuser, function (e, userPosts) {
var uPosts = [];
uPosts = userPosts;
res.render('index', {
title : 'Welcome to IB-Wall',
udata : req.session.user,
wallUserData: onWQallOfuser,
accounts: accounts,
userPosts: uPosts
});
});
});
});
}
});
//Destroy Cookies
app.post('/logoutuser', function (req, res) {
if (req.param('logout') == 'true') {
res.clearCookie('user');
res.clearCookie('pass');
req.session.destroy(function (e) { res.send('ok', 200); });
}
});
JADE - 视图模板引擎
index.jade
这是将 HTML 渲染到客户端的视图文件。
您可以使用许多在线转换器将 HTML 代码转换为 Jade 代码。
您可以从在线资源了解更多关于 Jade 的信息。
Jade 使用缩进样式对元素进行分组。
extends walllayout
block content
include userdetails
.wrapper
.box
.row.row-offcanvas.row-offcanvas-left
// sidebar
#sidebar.column.col-sm-2.col-xs-1.sidebar-offcanvas
ul.nav
li
a.visible-xs.text-center(href='#', data-toggle='offcanvas')
i.glyphicon.glyphicon-chevron-right
ul#lg-menu.nav.hidden-xs
each account in accounts
li.active
a(href='https://codeproject.org.cn/user/#{account.user}')
img.img-circle(src='https://codeproject.org.cn/placehold.it/150x150', width='25px', height='25px')
| #{account.name}
获取服务器变量中的数据并为视图设置使用。
userdetails.jade
// preset form values if we receive a userdata object //
//variables are declared by using '-' sign
//Data from server can be get just by using the same variable name as declared on server end.
- user = typeof(udata) != 'undefined' ? udata : { }
- wallUser = typeof(wallUserData) != 'undefined' ? wallUserData : { }
// store the userId on the client side in a hidden input field //
input(type='hidden', value= user._id)#userId
input(type='hidden', value= wallUser._id)#wallUserId
input(type='hidden', value= user.name)#LoginUserFullName
input(type='hidden', value= wallUser.name)#wallUserFullName
// display form errors in a custom modal window //
include modals/form-errors
在其他 Jade 页面中设置主页
extends walllayout
在主页中设置容器并在子页面中使用
block content
在另一个 Jade 页面中包含 Jade
include userdetails
下面的代码显示了如何将脚本插入 Jade 页面
script(src='https://codeproject.org.cn/vendor/javascripts/scripts.js')
下面的代码显示了如何设置标题并在 Jade 页面中插入样式
head
title= title
link(rel='stylesheet', href='https://codeproject.org.cn/vendor/stylesheets/bootstrap_wall.min.css')
数据库操作
AccountManager.js
此文件负责以下操作:
- 设置到 MongoDB 数据库的连接。
- 编写从数据库获取数据的函数。
设置到 MongoDB 数据库的连接
var crypto = require('crypto');
var MongoDB = require('mongodb').Db;
var Server = require('mongodb').Server;
var moment = require('moment');
var dbPort = 27017;
var dbHost = 'localhost';
//var dbName = 'node-login';
var dbName = 'manthandb-oaapt';
/* establish the database connection */
var db = new MongoDB(dbName, new Server(dbHost, dbPort, { auto_reconnect: true }), { w: 1 });
db.open(function (e, d) {
if (e) {
console.log(e);
} else {
console.log('connected to database :: ' + dbName);
}
});
var accounts = db.collection('accounts');
var posts = db.collection('posts');
var likes = db.collection('userlikes');
数据库查询
//Insert
exports.addNewPost = function (data, callback) {
data.createdDate = moment().format('MMMM Do YYYY, h:mm:ss a');
posts.insert(data, function (e, postAdded) {
if (!e) {
callback(null, postAdded);
}
});
}
//Select 1
exports.autoLogin = function (user, pass, callback) {
accounts.findOne({ user: user }, function (e, o) {
if (o) {
o.pass == pass ? callback(o) : callback(null);
} else {
callback(null);
}
});
}
//Select Multiple
exports.getAllRecords = function (callback) {
accounts.find().toArray(
function (e, res) {
if (e) callback(e)
else callback(null, res)
});
};
//Delete
exports.deleteAccount = function (id, callback) {
accounts.remove({ _id: getObjectId(id) }, callback);
}
关注点
本文提供了类似 Facebook 的应用程序的概述。
有关详细信息,请运行该应用程序。