玩轉(zhuǎn)nodejs

Node.js的誕生

Nodejs的創(chuàng)始人Rayn Dahl

Nodejs的創(chuàng)始人Rayn Dahl發(fā)現(xiàn)PHP這種腳本語(yǔ)言,在處理網(wǎng)頁(yè)請(qǐng)求的時(shí)候,隨著訪問(wèn)量上來(lái)物遇,要讓W(xué)eb業(yè)務(wù)支持更多的用戶俩功,就需要增加服務(wù)器的配置或者增加搭建集群,則這個(gè)時(shí)候的成本就上升了扔傅。

Rayn Dahl這個(gè)時(shí)候?qū)hrome瀏覽器的V8引擎(目前世界上最快的JS解析引擎)移植到了服務(wù)器上耍共,開(kāi)發(fā)出了Node.js平臺(tái)。

2009年底猎塞,Ryan Dahl在柏林舉行的JSConf EU會(huì)議上發(fā)表關(guān)于Node.js的演講试读,之后Node.js逐漸流行于世。

Node.js是一個(gè)平臺(tái)不是一個(gè)語(yǔ)言荠耽,開(kāi)發(fā)語(yǔ)言仍然是JavaScript钩骇。此時(shí)Node.js平臺(tái)可以讓我們用JavaScript語(yǔ)言來(lái)開(kāi)發(fā)服務(wù)器程序。

Node.js的安裝

node.js可以安裝在windows铝量、mac伊履、linux上,只需要下載對(duì)應(yīng)平臺(tái)的軟件即可款违。

nodejs官網(wǎng):http://nodejs.org/

nodejs中文網(wǎng):http://nodejs.cn/

本次使用 8.7.0 這個(gè)版本進(jìn)行演示唐瀑。
下載對(duì)應(yīng)的版本后,全程下一步進(jìn)行安裝即可插爹。

Node.js的入門(mén)使用

javascript需要宿主環(huán)境才能運(yùn)行哄辣。一般來(lái)說(shuō)我們的瀏覽器可以提供該環(huán)境请梢;但是nodejs平臺(tái)也可以提供該環(huán)境。

在nodejs平臺(tái)中運(yùn)行js文件力穗,此時(shí)需要使用CMD窗口毅弧。此時(shí)需要將CMD的“光標(biāo)路徑”更改為我們的項(xiàng)目文件夾。在對(duì)應(yīng)的文件里面編寫(xiě)代碼当窗,然后使用node運(yùn)行即可够坐。


> node demo1.js

由于nodejs平臺(tái)沒(méi)有DOM所以不能使用下面的語(yǔ)法:
window、document崖面、alert元咙、document.getElementById()……

但是nodejs能夠識(shí)別函數(shù)、if語(yǔ)句巫员、for庶香、while等等js核心語(yǔ)法。

nodejs常見(jiàn)模塊

http模塊

nodejs中的內(nèi)置模塊http模塊简识,可以提供web服務(wù)赶掖。


// 得到內(nèi)置http模塊
var http = require("http");

//創(chuàng)建服務(wù)器,使用createServer方法來(lái)創(chuàng)建服務(wù)器七扰。
//回調(diào)函數(shù)中有一個(gè)req參數(shù)表示請(qǐng)求奢赂,res參數(shù)表示響應(yīng)。
var server = http.createServer(function(req,res){
      res.setHeader("Content-Type","text/html;charset=UTF8");
    //輸出
      res.write("哈哈");
      res.end("Hello World!!!");
});

// 監(jiān)聽(tīng)3000端口
server.listen(3000);

fs模塊

fs是nodejs提供的一個(gè)用于讀取磁盤(pán)文件的模塊

fs模塊最重要的api就是readFile颈走,可以異步讀取文件膳灶,第一個(gè)參數(shù)就是要讀取的文件路徑(注意:必須以./開(kāi)頭,表示從當(dāng)前js文件出發(fā)尋找文件)疫鹊。第二個(gè)參數(shù)是回調(diào)函數(shù)袖瞻,表示讀取完畢之后做的事情司致。


var fs = require('fs');

fs.readFile("./data.txt" , function(err , data){
    console.log(data);
});

Express框架

問(wèn)題引入

做http服務(wù)的時(shí)候拆吆,不方便:

  1. 匹配URL很不方便
  2. 使用靜態(tài)頁(yè)面不方便 fs.readFile(function(err,data){res.end(data)})
  3. 不能靜態(tài)化一個(gè)文件夾,我們想將一個(gè)文件夾中的所有文件自動(dòng)擁有路由脂矫,實(shí)現(xiàn)不了

Express簡(jiǎn)化了HTTP應(yīng)用程序的開(kāi)發(fā)枣耀。

cnpm intsall --save express

創(chuàng)建app和app的監(jiān)聽(tīng)

我們引入express之后,這個(gè)express是一個(gè)函數(shù)庭再,這個(gè)函數(shù)可以調(diào)用創(chuàng)建出一個(gè)app對(duì)象捞奕。
今后所有的操作都是用app對(duì)象來(lái)完成,需要注意的是拄轻,一個(gè)程序中只有一個(gè)app颅围。
也就是說(shuō)express不能多次調(diào)用。

var express = require("express");
var app = express();
//  業(yè)務(wù)代碼

app.listen(3000);

中間件

app.動(dòng)詞("地址" , function(req,res){

});

// 示例

var express = require("express");
var app = express();

app.get("/get" , function(req,res){
    console.log("get");
});

app.post("/post" , function(req,res){
    console.log("post");
});

app.listen(3000);

中間件通配符-get參數(shù)

用:來(lái)表示表示一個(gè)通配恨搓,在程序中可以通過(guò)req.params.***得到它院促。


app.get("/:uid/:typeid" , function(req,res){
    var uid = req.params.uid;
    var typeid = req.params.typeid;

    res.send(uid + typeid);
});

用next()放行攔截

當(dāng)一個(gè)中間件已經(jīng)匹配了路徑筏养,但是自己不希望單獨(dú)處理這次請(qǐng)求,可以用next來(lái)放行常拓。

輸出

輸出可以用res.send()做輸出渐溶,會(huì)自動(dòng)加上utf-8。

  1. res.send("中文");
  2. res.json({"username":"andy"});
  3. res.jsonp({"username":"andy"}); // 如果輸出的內(nèi)容是一個(gè)JSONP弄抬,此時(shí)要用res.jsonp()來(lái)輸出茎辐,此時(shí)它會(huì)自動(dòng)檢測(cè)callback的GET請(qǐng)求,并且加上圓括號(hào)的調(diào)用掂恕。
  4. res.sendFile(__dirname + "/public/index.html");//如果輸出的是一個(gè)外置頁(yè)面拖陆,此時(shí)要用sendFile()這個(gè)API,注意這里必須要用絕對(duì)路徑竹海,此時(shí)我們用__dirname來(lái)進(jìn)行一個(gè)拼合慕蔚。
  5. res.redirect("http://www.163.com");//如果想要跳轉(zhuǎn)頁(yè)面,用res.redirect()即可

靜態(tài)化一個(gè)文件夾

如果我們想讓某文件夾中的所有文件自動(dòng)擁有路由斋配,此時(shí)非常簡(jiǎn)單孔飒,一句話即可。


app.use( express.static("public") );
//更進(jìn)一步艰争,如果我們不希望靜態(tài)的文件夾出現(xiàn)在底層坏瞄,而是在URL中體現(xiàn)public的名字。

app.use("/public" , express.static("public"));

Express中的GET請(qǐng)求和POST請(qǐng)求參數(shù)

GET請(qǐng)求參數(shù)的獲得

GET請(qǐng)求參數(shù)的識(shí)別實(shí)際上就是URL地址的解析甩卓。URL解析使用內(nèi)置的url模塊的parse方法即可鸠匀。

var url = require("url");
app.get("/users" , function(req,res){
    var query = url.parse(req.url , true).query;
    console.log("服務(wù)器收到了前端交來(lái)的數(shù)據(jù)" , query);
});

POST請(qǐng)求參數(shù)的獲得

POST請(qǐng)求的參數(shù)攜帶在上行報(bào)文的報(bào)文體中。
我們使用npm包formidable來(lái)識(shí)別這樣的上行報(bào)文逾柿。

API:https://www.npmjs.com/package/formidable


cnpm intsall formidable --save

var formidable = require('formidable');
app.post("/posts" , function(req,res){
    var form = new formidable.IncomingForm();

    form.parse(req , function(err , fields , files){
        console.log( fields );
    });
});


其他請(qǐng)求

注意只有GET請(qǐng)求是通過(guò)URL綴?參數(shù)來(lái)傳遞參數(shù)的缀棍。其他的http請(qǐng)求,都是通過(guò)上行報(bào)文來(lái)傳參數(shù)的。formidable能夠識(shí)別其他的請(qǐng)求的參數(shù)式矫。

MongoDB

NoSQL簡(jiǎn)介

NoSQL就是除開(kāi)關(guān)系型數(shù)據(jù)庫(kù)的統(tǒng)稱行疏。

MongoDB數(shù)據(jù)庫(kù)的安裝

https://www.mongodb.com/

mongobooster可視化數(shù)據(jù)庫(kù)管理軟件

NodeJS操作MongoDB

手冊(cè):https://docs.mongodb.com/ecosystem/drivers/node-js/
或者:https://www.npmjs.com/package/mongodb

> cnpm install --save mongodb

var MongoClient = require('mongodb').MongoClient;

//數(shù)據(jù)庫(kù)的地址,最末尾的斜杠是數(shù)據(jù)庫(kù)的名稱
var url = 'mongodb://localhost:27017/ceshi';

MongoClient.connect(url, function(err, db) {
    if(!err){
        console.log("數(shù)據(jù)庫(kù)連接成功");
    }else{
        console.log("數(shù)據(jù)庫(kù)連接失敗");
        return;
    }

    //查詢
    db.collection("collect1").find({}).toArray(function(err , docs){
        console.log(docs);
    });

    //增加
    db.collection("collect1").insert({"name":"asion", "age":23},function(err){
        if(!err){
            console.log("插入成功");
        }
    });

});

原生nodejs操作mongodb問(wèn)題很多:

  1. 語(yǔ)法形式上大的回調(diào)函數(shù)太大了青瀑,要包裹所有的代碼,甚至要包裹express的中間件萧诫;
  2. 不利于MVC編程斥难,因?yàn)檫@些寫(xiě)代碼幾乎不能將所有對(duì)數(shù)據(jù)庫(kù)的操作封裝到一個(gè)文件中。

Mongoose

簡(jiǎn)介

Mongoose簡(jiǎn)化了nodejs對(duì)nodejs的操作帘饶。

安裝

> cnpm install --save mongoose

基本使用

  1. 創(chuàng)建schema哑诊,根據(jù)schema創(chuàng)建model
var mongoose = require("mongoose");

//創(chuàng)建schema
var studentSchema = new mongoose.Schema({
    "id"    : Number, 
    "username"  : String,
    "age"       : Number,
    "gender"        : String
});

//通過(guò)schema創(chuàng)建model 對(duì)一個(gè)參數(shù)代表是集合的名稱,到時(shí)候會(huì)在mongodb里面轉(zhuǎn)換為小寫(xiě)及刻,并且轉(zhuǎn)換為復(fù)數(shù)形式
var Student = mongoose.model("Student" , studentSchema);

//暴露
module.exports = Student;

  1. 根據(jù)模型得到實(shí)例化對(duì)象

var mongoose = require('mongoose');

//連接數(shù)據(jù)庫(kù)
mongoose.connect('mongodb://localhost/xsgl');

//連接我們的model
var Student = require("./models/Student.js");

//實(shí)例化一個(gè)Student類的實(shí)例:
var xiaoming = new Student({
    "id" : 10001 ,
    "age" : 12,
    "gender" : "男",
    "username" : "小明"
});

//調(diào)用它的save方法即可放到數(shù)據(jù)庫(kù)中持久化
xiaoming.save(function(err){
    if(err){
        console.log("保存失敗");
    }else{
        console.log("保存成功");
    }
});


curd操作

增加

// 方式一
var xiaoming= new Student({
    "id" : 10001 ,
    "age" : 12,
    "gender" : "男",
    "username" : "小明"
});

xiaoming.save((err)=>{
    !err && console.log("成功");
});

// 方式二
Student.create({
    "id" : 10001 ,
    "age" : 12,
    "gender" : "男",
    "username" : "小明"
},(err)=>{
    !err && console.log("成功");


// 方式一:先查詢記錄镀裤,然后remove
Student.find({"username" : "asion"} , function(err , results){
    var rs= results[0];
    rs.remove((err)=>{
        !err && console.log("成功");
    });
});
// 方式二:
Student.remove({"username" : "asion"} , (err)=>{
    !err && console.log("成功");
});


// 方式一
Student.find({"username" : "asion"} , function(err , results){
    var thepeople = results[0];

    thepeople.sex = "女";

    thepeople.save((err)=>{
        !err && console.log("成功");
    });
});
// 方式二:
Student.update({"username" : "asion"} , {"$set" : {"age" : 99}} , function(err){
    !err && console.log("成功");
});


Student.find({"username" : "asion"} , function(err , results){

});

模板引擎

簡(jiǎn)介

如果要使用模板引擎穷当,分為如下四步:

  1. 安裝依賴,npm install --save ejs
  2. 設(shè)置默認(rèn)模板引擎 app.set("view engine" , "ejs");
  3. 在views文件夾中創(chuàng)建一個(gè).ejs后綴的頁(yè)面淹禾,就是模板
  4. 在express的中間件中用res.render()來(lái)呈遞視圖馁菜,語(yǔ)法就是res.render(模板文件名字 , {字典});

安裝模板引擎


> cnpm install --save express ejs

// 視圖代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <div class="wrap">
        <h1><%=content%></h1>
    </div>
</body>
</html>

// 業(yè)務(wù)代碼

var express = require("express");
var app = express();

//設(shè)置默認(rèn)模板引擎為ejs
app.set("view engine" , "ejs");

app.get("/" , function(req,res){
    //現(xiàn)在多了一個(gè)res.render()表示使用模板頁(yè)面
    //不需要加上views文件夾,因?yàn)槟0逡婺J(rèn)就是放在views文件夾中的铃岔,也不需要加上.ejs后綴
    res.render("detail" , {
        "contente" : "網(wǎng)頁(yè)內(nèi)容"
    });
});

app.listen(3000);



注意事項(xiàng)

  1. views文件夾可以改變汪疮,使用語(yǔ)句
app.set("views" , "templates");
// 這樣所有的.ejs文件都要放到 templates文件夾中。
  1. 拓展名必須是.ejs毁习,render的時(shí)候不需要寫(xiě).ejs
  2. 可以使用一些for循環(huán)和if語(yǔ)句
<ul>
    <% for(var i = 0 ; i < data.length ; i++){ %>
        <li><%= data[i] %></li>
    <% } %>
</ul>

// <% %>表示for循環(huán)智嚷、if語(yǔ)句;
// <%= %>表示輸出

擴(kuò)展

其他的模板引擎pug(原名叫做Jade):

https://www.npmjs.com/package/pug

cookie和session

簡(jiǎn)介

HTTP是無(wú)連接的纺且,所以產(chǎn)生了身份識(shí)別問(wèn)題

使用

express中使用cookie需要安裝一個(gè)依賴cookie-parser


> cnpm install --save cookie-parser
// 設(shè)置
res.cookie('uid', 1, { maxAge: 86400 });

// 讀取
var cookieParser = require('cookie-parser');
app.use(cookieParser());
//中間件中
app.get("/users" , function(req,res){
    req.cookies.uid;
});


session

session在express中的使用盏道,需要npm包:express-session。


> npm install --save express express-session ejs

app.post("/login" , function(req,res){
    var form = new formidable.IncomingForm();
    form.parse(req , function(err , fields){
                // 設(shè)置session數(shù)據(jù)
        req.session.login = true;
        req.session.username= "andy";

    });
});

文件上傳

頭像的上傳很簡(jiǎn)單载碌,因?yàn)閒ormidable天生支持文件的上傳猜嘱,用files來(lái)接收即可。

gm圖片裁剪

http://www.graphicsmagick.org/

> cnpm install --save gm

var gm = require('gm');
gm(avatarurl).crop(w,h,x,y).write(avatarurl, function (err) {
    console.log("裁剪成功嫁艇!");
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朗伶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子步咪,更是在濱河造成了極大的恐慌论皆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猾漫,死亡現(xiàn)場(chǎng)離奇詭異点晴,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)悯周,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)粒督,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人队橙,你說(shuō)我怎么就攤上這事坠陈∪螅” “怎么了捐康?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)庸蔼。 經(jīng)常有香客問(wèn)我解总,道長(zhǎng),這世上最難降的妖魔是什么姐仅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任花枫,我火速辦了婚禮刻盐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘劳翰。我一直安慰自己敦锌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布佳簸。 她就那樣靜靜地躺著乙墙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪生均。 梳的紋絲不亂的頭發(fā)上听想,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音马胧,去河邊找鬼汉买。 笑死,一個(gè)胖子當(dāng)著我的面吹牛佩脊,可吹牛的內(nèi)容都是我干的蛙粘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼威彰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼组题!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起抱冷,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤崔列,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后旺遮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赵讯,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年耿眉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了边翼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸣剪,死狀恐怖组底,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筐骇,我是刑警寧澤债鸡,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站铛纬,受9級(jí)特大地震影響厌均,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜告唆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一棺弊、第九天 我趴在偏房一處隱蔽的房頂上張望晶密。 院中可真熱鬧,春花似錦模她、人聲如沸稻艰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)连锯。三九已至,卻和暖如春用狱,著一層夾襖步出監(jiān)牢的瞬間运怖,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工夏伊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摇展,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓溺忧,卻偏偏與公主長(zhǎng)得像咏连,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲁森,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容