nodejs教程之環(huán)境安裝及運(yùn)行
讓nodeJS跑起來
第一步當(dāng)然是安裝nodeJS環(huán)境了,現(xiàn)在windows安裝nodeJS比較快了,直接下載即可:
http://www.nodejs.org/download/
這里根據(jù)需要下載,下載完成后直接下一步下一步即可,完了我們就具有nodeJS環(huán)境了
第二步,為了方便我們后面操作,我們直接在D盤見了一個(gè)文件夾blog
然后打開windows命令行工具,進(jìn)入d盤,輸入:
然后里面可能有依賴包,我們需要進(jìn)入blog目錄安裝(安裝的配置由package.json提供):
這個(gè)樣子,我們依賴包就下載下來了,其中依賴包與java的包文件,.net的bll文件應(yīng)該是一個(gè)概念
這個(gè)時(shí)候,我們的程序已經(jīng)可以運(yùn)行了:
這個(gè)時(shí)候打開瀏覽器就有反應(yīng)了:
這里我們使用的是express(一個(gè)流行的nodeJSweb開發(fā)框架),并且使用了ejs模板引擎
文件結(jié)構(gòu)
初始化文件目錄結(jié)構(gòu)如下:
app.js 為入口文件
package.json 為模塊依賴文件,我們使用npm install時(shí)候他會(huì)以其配置在網(wǎng)上下載相關(guān)包
node_modules 為下載下來的模塊文件(package.json)
public 存放靜態(tài)資源文件
routes 存放路由文件
views 存放相關(guān)視圖模板文件
這個(gè)樣子,我們基本目錄結(jié)構(gòu)就出來了,我們這里先簡單說下node_modules這個(gè)目錄
node_modules/ejs
我們剛剛說了,這里面存放著下載下來的模塊,說白了就是js文件集合
var parse = exports.parse = function(str, options){
var options = options || {}
, open = options.open || exports.open || '<%'
, close = options.close || exports.close || '%>'
, filename = options.filename
, compileDebug = options.compileDebug !== false
, buf = "";
buf += 'var buf = [];';
if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ ';
buf += '\n buf.push(\'';
var lineno = 1;
var consumeEOL = false;
for (var i = 0, len = str.length; i < len; ++i) {
var stri = str[i];
if (str.slice(i, open.length + i) == open) {
i += open.length
var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno;
switch (str[i]) {
case '=':
prefix = "', escape((" + line + ', ';
postfix = ")), '";
++i;
break;
case '-':
prefix = "', (" + line + ', ';
postfix = "), '";
++i;
break;
default:
prefix = "');" + line + ';';
postfix = "; buf.push('";
}
var end = str.indexOf(close, i)
, js = str.substring(i, end)
, start = i
, include = null
, n = 0;
if ('-' == js[js.length-1]){
js = js.substring(0, js.length - 2);
consumeEOL = true;
}
if (0 == js.trim().indexOf('include')) {
var name = js.trim().slice(7).trim();
if (!filename) throw new Error('filename option is required for includes');
var path = resolveInclude(name, filename);
include = read(path, 'utf8');
include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
buf += "' + (function(){" + include + "})() + '";
js = '';
}
while (~(n = js.indexOf("\n", n))) n++, lineno++;
if (js.substr(0, 1) == ':') js = filtered(js);
if (js) {
if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n';
buf += prefix;
buf += js;
buf += postfix;
}
i += end - start + close.length - 1;
} else if (stri == "\\") {
buf += "\\\\";
} else if (stri == "'") {
buf += "\\'";
} else if (stri == "\r") {
// ignore
} else if (stri == "\n") {
if (consumeEOL) {
consumeEOL = false;
} else {
buf += "\\n";
lineno++;
}
} else {
buf += stri;
}
}
if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');";
else buf += "');\nreturn buf.join('');";
return buf;
};
就如,我們這里使用到的ejs模板以及express模塊,然后我們好奇的走進(jìn)了ejs的程序看看究竟有何不同
打開,ejs.js后,我們抽一點(diǎn)代碼出來看:這段代碼我們比較熟悉,他與underscore的模板引擎代碼思想一致,都是將模板解析為字符串
然后通過eval或者new Function的方法將之轉(zhuǎn)換為函數(shù),并且傳入自己的數(shù)據(jù)對(duì)象好解析
至于具體工作流程,現(xiàn)在我們還不知道,只能放到后面點(diǎn)研究了,好了我們現(xiàn)在進(jìn)入其他模塊
app.js
作為入口文件,app.js扮演著舉足輕重的角色:
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
我們通過require()命令加載express、http模塊,并且會(huì)加載routes目錄下index user等模板文件
app.set('port', process.env.PORT || 3000)為設(shè)置啟動(dòng)時(shí)候的端口
app.set('views', __dirname + '/views')為設(shè)置存放模板文件的路徑,其中__dirname為全局變量,存放當(dāng)前腳本所在目錄,我們這樣可以查看:
console.log(__dirname);//index.js加入以下代碼
/**
D:\blog>node app
Express server li
D:\blog\routes
*/
至于這個(gè)__dirname是如何獲得的,我們暫時(shí)也不需要關(guān)注
app.set('view engine', 'ejs') 為設(shè)置模板引擎為ejs
app.use(express.favicon())是設(shè)置圖標(biāo)想修改的話就自己去搞public下面的images文件
app.use(express.logger('dev')); express依賴于connect這里就內(nèi)建中間件會(huì)輸出一些日志
app.use(express.json()); 用以解析請(qǐng)求體,這里就會(huì)把字符串動(dòng)態(tài)轉(zhuǎn)換為json對(duì)象
app.use(express.methodOverride()); connect內(nèi)建中間件,用以處理post請(qǐng)求,并可以偽裝put等http方法
app.use(app.router); 調(diào)用路由器解析規(guī)則
app.use(express.static(path.join(__dirname, 'public'))); connect內(nèi)建中間件,設(shè)置根目錄下的public存放靜態(tài)文件
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
這句話意思是開發(fā)狀況下要輸出錯(cuò)誤信息
app.get('/', routes.index);
app.get('/users', user.list);
這兩句都是訪問時(shí)刻具體的處理文件了,比如這里直接訪問時(shí)默認(rèn)訪問的是routes.index
然后其內(nèi)部才真正解析模板數(shù)據(jù):
exports.index = function (req, res) {
console.log(__dirname);
res.render('index', { title: 'Express' });
};
最后會(huì)調(diào)用上述代碼創(chuàng)建http服務(wù)器并監(jiān)聽3000端口,成功后便可在網(wǎng)頁上訪問了
路由
前面我們使用這個(gè)方法構(gòu)建路由
上面代碼可以使用這個(gè)代碼取代(寫在app里面)
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
這段代碼的意思是訪問主頁時(shí),調(diào)用ejs模板引擎,來渲染index.ejs模板文件
現(xiàn)在再做一點(diǎn)修改,以上代碼實(shí)現(xiàn)了路由功能,但是我們不能將路由相關(guān)代碼放到app中,路由多了后app就會(huì)變得臃腫,所以我們將相關(guān)配置放入index中
所以刪除app中相關(guān)路由功能,在app結(jié)尾加入代碼:
然后修改index.js
module.exports = function(app) {
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
};
這個(gè)代碼是怎么組織的現(xiàn)在還不清楚,也不去關(guān)注了,我們后面慢慢看
路由規(guī)則
express封裝了多種http請(qǐng)求,我們一般使用get/post兩種
app.get();
app.post();
第一個(gè)參數(shù)為請(qǐng)求路徑,第二個(gè)參數(shù)為回調(diào)函數(shù),還是兩個(gè)參數(shù)為request與response
然后,對(duì)于req(request)又有以下規(guī)則
req.query 處理get請(qǐng)求,獲取get請(qǐng)求參數(shù)
req.params 處理/:xxx形式的get或者post請(qǐng)求
req.body 處理post請(qǐng)求,獲取post請(qǐng)求體
req.params 處理get和post請(qǐng)求,但查找優(yōu)先級(jí)為req.params->req.body->req.query
路徑規(guī)則還支持正則,具體我們以后再說......
添加路由規(guī)則
當(dāng)我們?cè)L問不存在的鏈接時(shí):
因?yàn)椴淮嬖?y的路由規(guī)則,他也不說public下的文件,所以就404了
現(xiàn)在我們?cè)趇ndex.js中添加相關(guān)路由:
module.exports = function (app) {
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
app.get('/y', function (req, res) {
res.send('葉小釵');
});
};
這里我頁面亂碼了:
原因是下載下來后,我的文件是gbk的編碼,我們要將他改成utf-8就可以了,模板引擎這塊我們就不管他了,我們進(jìn)入下一節(jié)
注冊(cè)功能
這里我們跟著原博主一起做一個(gè)注冊(cè)的簡單功能,這里使用mongo db作為數(shù)據(jù)庫,后面我們?cè)僖来瓮晟乒δ?/p>
新建一個(gè)register路由,并且為其新建register模板,于是我們開始吧
① 在index中新建路由
app.get('/register', function (req, res) {
res.render('index', { title: '注冊(cè)頁面' });
});
module.exports = function (app) {
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
app.get('/y', function (req, res) {
res.send('葉小釵');
});
app.get('/register', function (req, res) {
res.render('register', { title: '注冊(cè)頁面' });
});
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<form method="post">
<div>用戶名:<input type="text" name="name"/></div>
<div>密碼:<input type="password" name="password"/></div>
<div><input type="submit" value="登陸"/></div>
</form>
</body>
</html>
這個(gè)樣子,我們頁面就形成了:
基本程序有了,我們現(xiàn)在需要數(shù)據(jù)庫支持,于是我們要安裝mongoDB環(huán)境
MongoDB
MongoDB是一個(gè)基于分布式文件存儲(chǔ)的NoSQL的一種,由C++編寫,MongoDB支持的數(shù)據(jù)結(jié)構(gòu)松散,類似json,我們知道json可以支持任何類型,所以可以搞出很復(fù)雜的結(jié)構(gòu)
{
id: 1,
name: '葉小釵',
frinds: [
{ id: 2, name: '素還真' },
{ id: 3, name: '一頁書' }
]
}
安裝MongoDB
首先去http://www.mongodb.org/downloads下載安裝文件,然后將文件拷貝到D盤改名mongodb,然后在里面新建blog文件夾
然后打開命令行工具將目錄切換至bin,輸入:
設(shè)置blog文件夾為工程目錄并啟動(dòng)數(shù)據(jù)庫,為了方便以后我們寫一個(gè)命令以后直接點(diǎn)擊就啟動(dòng)數(shù)據(jù)庫了:
鏈接MongoDB
數(shù)據(jù)庫安裝成功后,我們的程序還需要相關(guān)的“驅(qū)動(dòng)”程序才能鏈接數(shù)據(jù)庫,這個(gè)時(shí)候當(dāng)然要下載包......
打開package.json在dependencies新加一行
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.4.8",
"ejs": "*",
"mongodb": "*"
}
}
然后運(yùn)行npm install下載新的依賴包,這個(gè)樣子與mongoDB相關(guān)的驅(qū)動(dòng)就有了,要鏈接mysql等數(shù)據(jù)庫還需要其他依賴包
這時(shí)在根目錄下創(chuàng)建setting.js文件,保存數(shù)據(jù)庫連接信息
module.exports = {
cookieSecret: 'myblog',
db: 'blog',
host: 'localhost'
};
db是數(shù)據(jù)庫名稱,host是數(shù)據(jù)庫地址,cookieSecret用于cookie加密與數(shù)據(jù)庫無關(guān)
接下來根目錄下新建models文件夾,并在models文件夾下新建db.js
var settings = require('../settings'),
Db = require('mongodb').Db,
Connection = require('mongodb').Connection,
Server = require('mongodb').Server;
module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_PORT), {safe: true});
設(shè)置數(shù)據(jù)庫名,數(shù)據(jù)庫地址和數(shù)據(jù)庫端口創(chuàng)建一個(gè)數(shù)據(jù)庫實(shí)例,并通過module.exports導(dǎo)出實(shí)例,這樣就可以通過require對(duì)數(shù)據(jù)庫進(jìn)行讀寫
需要成功寫入數(shù)據(jù)庫,服務(wù)器端程序就需要處理post信息,于是我們?cè)趍odels文件夾下新建user.js
var mongodb = require('./db');
function User(user) {
this.name = user.name;
this.password = user.password;
};
module.exports = User;
//存儲(chǔ)用戶信息
User.prototype.save = function (callback) {
//要存入數(shù)據(jù)庫的用戶文檔
var user = {
name: this.name,
password: this.password
};
//打開數(shù)據(jù)庫
mongodb.open(function (err, db) {
if (err) {
return callback(err); //錯(cuò)誤,返回 err 信息
}
//讀取 users 集合
db.collection('users', function (err, collection) {
if (err) {
mongodb.close();
return callback(err); //錯(cuò)誤,返回 err 信息
}
//將用戶數(shù)據(jù)插入 users 集合
collection.insert(user, {
safe: true
}, function (err, user) {
mongodb.close();
if (err) {
return callback(err); //錯(cuò)誤,返回 err 信息
}
callback(null, user[0]); //成功!err 為 null,并返回存儲(chǔ)后的用戶文檔
});
});
});
};
//讀取用戶信息
User.get = function(name, callback) {
//打開數(shù)據(jù)庫
mongodb.open(function (err, db) {
if (err) {
return callback(err);//錯(cuò)誤,返回 err 信息
}
//讀取 users 集合
db.collection('users', function (err, collection) {
if (err) {
mongodb.close();
return callback(err);//錯(cuò)誤,返回 err 信息
}
//查找用戶名(name鍵)值為 name 一個(gè)文檔
collection.findOne({
name: name
}, function (err, user) {
mongodb.close();
if (err) {
return callback(err);//失?。》祷?err 信息
}
callback(null, user);//成功!返回查詢的用戶信息
});
});
});
};
這里一個(gè)寫數(shù)據(jù),一個(gè)讀數(shù)據(jù),處理程序有了,現(xiàn)在需要在index.js前面加上如下程序
再修改其中的app.post('/register')
app.post('/register', function (req, res) {
var name = req.body.name;
var pwd = req.body.password;
var newUser = new User({
name: name,
password: pwd
});
newUser.save(function (err, user) {
//相關(guān)操作,寫入session
res.send(user);
});
});
然后點(diǎn)擊注冊(cè)后便會(huì)有反應(yīng)了
如果此時(shí)不能確定是否寫入數(shù)據(jù)庫,便可進(jìn)入數(shù)據(jù)庫查詢一番,首先切換至數(shù)據(jù)庫目錄
輸入:
然后切換其數(shù)據(jù)庫連接至blog
最后輸入
我們大家就開心的看到數(shù)據(jù)寫入了,于是今天的學(xué)習(xí)暫時(shí)告一段落
結(jié)語
今天我們跟著一篇博客完成了從安裝到寫入數(shù)據(jù)庫的操作,明天讓我們來將其它方面加入,逐步深化nodeJS的學(xué)習(xí)
相關(guān)文章
Node.js在圖片模板上生成二維碼圖片并附帶底部文字說明實(shí)現(xiàn)詳解
這篇文章主要介紹了Node.js在圖片模板上生成二維碼圖片并附帶底部文字說明實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Node.js如何實(shí)現(xiàn)注冊(cè)郵箱激活功能 (常見)
今天了解了node如何實(shí)現(xiàn)郵箱激活功能,這個(gè)功能非常常見,當(dāng)我們注冊(cè)一個(gè)賬號(hào)時(shí),肯定會(huì)有這步,下面看下如何實(shí)現(xiàn)這個(gè)功能2017-07-07nodejs基于express實(shí)現(xiàn)文件上傳的方法
這篇文章主要介紹了nodejs基于express實(shí)現(xiàn)文件上傳的方法,結(jié)合實(shí)例形式分析了nodejs基于express框架實(shí)現(xiàn)文件上傳功能的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2018-03-03Node.js的模塊化機(jī)制和Buffer對(duì)象詳解
這篇文章主要為大家詳細(xì)介紹了Node.js的模塊化機(jī)制和Buffer對(duì)象,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02Docker平臺(tái)下NodeJs?Puppeteer實(shí)現(xiàn)html轉(zhuǎn)pdf過程示例
這篇文章主要為大家介紹了Docker平臺(tái)下NodeJs?Puppeteer實(shí)現(xiàn)html轉(zhuǎn)pdf過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12