玩轉(zhuǎn)nodejs

Node.js的誕生

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

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

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

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

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

Node.js的安裝

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

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

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

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

Node.js的入門使用

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

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


> node demo1.js

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

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

nodejs常見模塊

http模塊

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


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

//創(chuàng)建服務(wù)器,使用createServer方法來創(chuàng)建服務(wù)器。
//回調(diào)函數(shù)中有一個(gè)req參數(shù)表示請求,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)聽3000端口
server.listen(3000);

fs模塊

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

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


var fs = require('fs');

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

Express框架

問題引入

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

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

Express簡化了HTTP應(yīng)用程序的開發(fā)。

cnpm intsall --save express

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

我們引入express之后,這個(gè)express是一個(gè)函數(shù),這個(gè)函數(shù)可以調(diào)用創(chuàng)建出一個(gè)app對象。
今后所有的操作都是用app對象來完成,需要注意的是,一個(gè)程序中只有一個(gè)app。
也就是說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ù)

用:來表示表示一個(gè)通配,在程序中可以通過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ú)處理這次請求,可以用next來放行。

輸出

輸出可以用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()來輸出,此時(shí)它會(huì)自動(dòng)檢測callback的GET請求,并且加上圓括號(hào)的調(diào)用。
  4. res.sendFile(__dirname + "/public/index.html");//如果輸出的是一個(gè)外置頁面,此時(shí)要用sendFile()這個(gè)API,注意這里必須要用絕對路徑,此時(shí)我們用__dirname來進(jìn)行一個(gè)拼合。
  5. res.redirect("http://www.163.com");//如果想要跳轉(zhuǎn)頁面,用res.redirect()即可

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

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


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

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

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

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

GET請求參數(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ù)器收到了前端交來的數(shù)據(jù)" , query);
});

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

POST請求的參數(shù)攜帶在上行報(bào)文的報(bào)文體中。
我們使用npm包formidable來識(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 );
    });
});


其他請求

注意只有GET請求是通過URL綴?參數(shù)來傳遞參數(shù)的。其他的http請求,都是通過上行報(bào)文來傳參數(shù)的。formidable能夠識(shí)別其他的請求的參數(shù)。

MongoDB

NoSQL簡介

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

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

https://www.mongodb.com/

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

NodeJS操作MongoDB

手冊: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ù)庫的地址,最末尾的斜杠是數(shù)據(jù)庫的名稱
var url = 'mongodb://localhost:27017/ceshi';

MongoClient.connect(url, function(err, db) {
    if(!err){
        console.log("數(shù)據(jù)庫連接成功");
    }else{
        console.log("數(shù)據(jù)庫連接失敗");
        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問題很多:

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

Mongoose

簡介

Mongoose簡化了nodejs對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
});

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

//暴露
module.exports = Student;

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

var mongoose = require('mongoose');

//連接數(shù)據(jù)庫
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ù)庫中持久化
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){

});

模板引擎

簡介

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

  1. 安裝依賴,npm install --save ejs
  2. 設(shè)置默認(rèn)模板引擎 app.set("view engine" , "ejs");
  3. 在views文件夾中創(chuàng)建一個(gè).ejs后綴的頁面,就是模板
  4. 在express的中間件中用res.render()來呈遞視圖,語法就是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()表示使用模板頁面
    //不需要加上views文件夾,因?yàn)槟0逡婺J(rèn)就是放在views文件夾中的,也不需要加上.ejs后綴
    res.render("detail" , {
        "contente" : "網(wǎng)頁內(nèi)容"
    });
});

app.listen(3000);



注意事項(xiàng)

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

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

擴(kuò)展

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

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

cookie和session

簡介

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

使用

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";

    });
});

文件上傳

頭像的上傳很簡單,因?yàn)閒ormidable天生支持文件的上傳,用files來接收即可。

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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容