天天看點

前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品

一. NodeJs簡介

1.1 nodeJs的誕生

在Netscape設計出JavaScript後的短短幾個月,JavaScript事實上已經是前端開發的唯一标準。後來,微軟通過IE擊敗了Netscape後一統桌面,結果幾年時間,浏覽器毫無進步。

沒有競争就沒有發展。微軟認為IE6浏覽器已經非常完善,幾乎沒有可改進之處,然後解散了IE6開發團隊!而Google卻認為支援現代Web應用的新一代浏覽器才剛剛起步,尤其是浏覽器負責運作JavaScript的引擎性能還可提升10倍。先是Mozilla借助已壯烈犧牲的Netscape遺産在2002年推出了Firefox浏覽器,緊接着Apple于2003年在開源的KHTML浏覽器的基礎上推出了WebKit核心的Safari浏覽器,不過僅限于Mac平台。随後,Google也開始建立自家的浏覽器。他們也看中了WebKit核心,于是基于WebKit核心推出了Chrome浏覽器。

Chrome浏覽器是跨Windows和Mac平台的,并且,Google認為要運作現代Web應用,浏覽器必須有一個性能非常強勁的JavaScript引擎,于是Google自己開發了一個高性能JavaScript引擎,名字叫V8引擎并且開源。

有個叫Ryan Dahl的歪果仁,他的工作是用C/C++寫高性能Web服務。對于高性能,異步IO、事件驅動是基本原則,但是用C/C++寫就太痛苦了。于是這位仁兄開始設想用進階語言開發Web服務。他評估了很多種進階語言,發現很多語言雖然同時提供了同步IO和異步IO,但是開發人員一旦用了同步IO,他們就再也懶得寫異步IO了,是以,最終,Ryan瞄向了JavaScript。因為JavaScript是單線程執行,根本不能進行同步IO操作,是以,JavaScript的這一“缺陷”導緻了它隻能使用異步IO。標明了開發語言,還要有運作時引擎。這位仁兄曾考慮過自己寫一個,不過明智地放棄了,因為V8就是開源的JavaScript引擎。讓Google投資去優化V8,咱隻負責改造一下拿來用,還不用付錢,這個買賣很劃算。于是在2009年,Ryan正式推出了基于JavaScript語言和V8引擎的開源Web伺服器項目,命名為Node.js。雖然名字很土,但是,Node第一次把JavaScript帶入到後端伺服器開發,加上世界上已經有無數的JavaScript開發人員,是以Node一下子就火了起來。

1.2 nodeJs的優勢

優勢是借助JavaScript天生的事件驅動機制加V8高性能引擎,使編寫高性能Web服務輕而易舉。其次,JavaScript語言本身是完善的函數式語言,在前端開發時,開發人員往往寫得比較随意,讓人感覺JavaScript就是個“玩具語言”。但是,在Node環境下,通過子產品化的JavaScript代碼,加上函數式程式設計,并且無需考慮浏覽器相容性問題,直接使用最新的ECMAScript 6标準,可以完全滿足工程上的需求。

二. 安裝NodeJs

2.1 nodeJs版本

  • 本課程中所用版本為node-v12.16.2的64位版本。
  • 在Windows上安裝時務必選擇全部元件,包括勾選Add to Path。

2.2 版本驗證

  • 打開指令提示符,然後輸入

    node -v

    ,如果安裝正确,結果如圖
前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品

2.3 node指令

  • 在指令提示符中輸入node,此時進入nodejs的互動環境。在該環境下支援輸入任意的JavaScript代碼,例如輸入200+200回車後得到輸出結果為400。
  • 連按兩次Ctrl+C退出nodeJs互動環境
前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品

三. NPM簡介

3.1 什麼是NPM

  • NPM(NodeJS Package Manager)就是nodejs的包(插件)管理工具。
  • NPM無需手動安裝,在nodeJs環境安裝成功後就已經自動安裝成功了NPM。
  • 在指令提示符輸入

    npm -v

    正确結果如圖
前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品

3.2 為什麼需要NPM

  • 我們在開發時,會用到很多别人寫好的JavaScript代碼,比如jQuery、bootstrap等。
  • 我們使用這些插件時,需要自己到官網去下載下傳代碼,解壓代碼然後再使用,非常繁瑣。
  • NPM就是來解決這個問題的。開發人員把自己開發的代碼子產品打包後釋出到NPM官網。
  • 使用時通過npm指令來進行安裝即可直接使用,無需關心代碼存在哪以及從哪去下載下傳。
  • 再者,當我們使用A子產品,而A子產品又依賴于B子產品的時候,NPM可以根據依賴關系,自動把需要的依賴包下載下傳并管理。

3.3 更改NPM鏡像

  • 由于npm的源在國外,是以國内使用者使用起來各種不友善,是以一般會把NPM資源位址改為國内的鏡像資源。目前最為主流的鏡像是淘寶網提供的NPM鏡像。
  • 淘寶鏡像倉庫位址:https://registry.npm.taobao.org/
  • 淘寶鏡像搜尋位址:https://npm.taobao.org/
  • 使用方式有兩種:
    1. 安裝cnpm後使用cnpm指令。

      該方式其實是安裝一個cnpm插件,安裝這個插件也是需要從國外位址來安裝,有可能失敗。安裝成功後使用才沒有後續問題。

    2. 更改npm配置資訊

      從根本上解決下載下傳包速度過慢的問題。推薦使用。

3.3.1 安裝cnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org
           

3.3.2 更改npm配置資訊

  • 更改方式
npm config set registry https://registry.npm.taobao.org
           
  • 驗證是否成功
npm config get registry
           

四. HelloWorld

  • 桌面開發
  1. 桌面建立文本文檔,重命名為helloworld.js
  2. 滑鼠右鍵選擇編輯
  3. 輸入

    console.log("hello world");

    并儲存。
  4. 在桌面按住shift的情況下滑鼠右鍵單擊,選擇

    在此處打開Powershell視窗

  5. 在powershell視窗中輸入

    node helloworld.js

    回車(輸入he之後按tab可以自動補全代碼)
  6. 第四部如果無法正常執行,則在說明win+r運作窗輸入cmd回車進入指令行編輯器。
  7. 輸入

    cd C:\Users\計算機使用者名\Desktop

    回車,表示進入桌面目錄
  8. 在指令編輯行視窗中輸入

    node helloworld.js

    回車(輸入he之後按tab可以自動補全代碼)

五. NodeJs子產品

5.1 子產品系統

5.1.1 什麼是子產品系統

在計算機程式的開發過程中,随着程式代碼越寫越多,在一個檔案裡代碼就會越來越長,越來越不容易維護。為了編寫可維護的代碼,我們把很多函數分組,分别放到不同的檔案裡,這樣,每個檔案包含的代碼就相對較少,很多程式設計語言都采用這種組織代碼的方式。在Node環境中,一個.js檔案就稱之為一個子產品(module)。

5.1.2 子產品系統的優勢

  1. 提高代碼的可維護性
  2. 提高代碼的可複用性
  3. 避免沖突

5.1.3 自定義子產品

  • 聲明自定義子產品
/*自定義函數test*/
function test(name) {
    console.log(`hello${name}`);
}
/*子產品輸出*/
module.exports=test;
           
  • 使用自定義子產品
/*require函數表示引入子產品,參數為要引入子產品的位址,可以是相對路徑或絕對路徑*/
// 注意,在nodejs中引入子產品使用的是require函數,在浏覽器中使用的import函數。
// 此處引入檔案時同檔案夾下也必須使用以./開頭表示的相對路徑,否則會報錯。
// 如果require中直接寫Hello,那麼Node會依次從内置子產品、全局子產品和目前子產品下尋找Hello.js
//子產品與子產品之間互相不幹擾,其底層實作原理是閉包。
let show = require('./Hello');	
/*聲明的變量show可以和require引入的子產品中通過module.exports輸出的函數名不同*/
show("張三");
/*目前子產品中繼續聲明test函數,和Hello子產品中的test是沒有關系的,不會産生沖突*/
function test() {
    console.log("第二個test")
}
test();
           
  • module.exports可以通過封裝對象來傳回多個值
function hello() {
    console.log('Hello, world!');
}

function greet(name) {
    console.log('Hello, ' + name + '!');
}

module.exports = {
    hello: hello,
    greet: greet
};
           

5.2 全局對象子產品

5.2.1 全局對象Global和Window對象

NodeJs 中有一個特殊的對象,稱為全局對象(Global Object),它及其所有屬性都可以在程式的任何地方通路,即全局變量。

在浏覽器 JavaScript 中,window 是全局對象, 而 Node.js 中的全局對象是 global,所有全局變量(除了 global 本身以外)都是 global 對象的屬性。

5.2.2 常用全局對象

  • __filename 輸出目前執行腳本的檔案名,包含路徑。
  • __dirname 輸出目前執行腳本所在目錄,包含路徑。
  • setTimeout和clearTimeout
  • setInterval和clearInterval
  • console
    1. console.log([data][, …])向标準輸出流列印字元并以換行符結束。該方法接收若幹 個參數,如果隻有一個參數,則輸出這個參數的字元串形式。如果有多個參數,則 以類似于C 語言 printf() 指令的格式輸出。
    2. console.info([data][, …])該指令的作用是傳回資訊性消息,這個指令與console.log差别并不大,除了在chrome中隻會輸出文字外,其餘的會顯示一個藍色的驚歎号。
    3. console.error([data][, …])輸出錯誤消息的。控制台在出現錯誤時會顯示是紅色的叉子。
    4. console.warn([data][, …])輸出警告消息。控制台出現有黃色的驚歎号。
    5. console.dir(obj[, options])用來對一個對象進行檢查(inspect),并以易于閱讀和列印的格式顯示。
    6. console.time(label)輸出時間,表示計時開始。
    7. console.timeEnd(label)結束時間,表示計時結束。

5.3 網絡子產品

5.3.1 http請求示例

/*引入http子產品*/
let http = require('http');
/**
 * 建立服務
 * request  請求傳入内容
 * response 請求輸出内容
 */
let server=http.createServer(function (request,response) {
    /*進行中文亂碼*/
    request.setEncoding("utf-8");
    response.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
    /*處理多請求一次的bug*/
    if(request.url!=='/favicon.ico'){
        /*輸出html内容到頁面*/
        response.write("<h1>hello world</h1>");
        /*輸出文本内容到頁面*/
        response.write("你好世界");
    }
    /*關閉輸出流,如果不調用end函數,則頁面會一直處于重新整理狀态*/
    response.end();
});
/*設定監聽端口*/
/*端口号範圍:0-65535,1023以内的端口号盡量不要使用!!!*/
server.listen(8888);
console.log(`啟動成功:http://localhost:8888`);
console.log(`常用預設端口号:https://blog.csdn.net/qiucheng_198806/article/details/87375505`);
           

5.3.2 get請求處理參數

const http = require('http');
const url = require('url');

http.createServer(function(request, response){
    request.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'});
    // 解析 url 參數
    const params = url.parse(request.url, true).query;
    response.write("網站名:" + params.name);
    response.write("\n");
    response.write("網站 URL:" + params.url);
    response.end();
}).listen(8888);
console.log("http://localhost:8888/user?name=zhangsan&url=http://www.zhihu.com");
           

5.3.3 post請求處理參數

const http = require('http');
const querystring = require('querystring');
http.createServer(function(request, response){
	//設定允許跨域的域名,*代表允許任意域名跨域
    request.header("Access-Control-Allow-Origin","*");
    // 定義了一個post變量,用于暫存請求體的資訊
    let post = '';
    // 通過req的data事件監聽函數,每當接受到請求體的資料,就累加到post變量中
    request.on('data', function(chunk){
        post += chunk;
    });
    // 在end事件觸發後,通過querystring.parse将post解析為真正的POST請求格式,然後向用戶端傳回。
    request.on('end', function(){
        post = querystring.parse(post);
        console.log(post);
        response.end();
    });
}).listen(8888);
           
  • 頁面代碼如下
<form action="http://localhost:8888" method="post">
    <div>
        <label for="username">使用者名</label>
        <input type="text" name="username" id="username">
    </div>
    <div>
        <label for="password">密碼</label>
        <input type="password" name="password" id="password">
    </div>
    <div>
        <button type="submit">送出</button>
    </div>
</form>
           

5.4 資料庫子產品

5.4.1 資料庫子產品為第三方子產品,需要單獨安裝

  1. 在目前項目檔案夾内打開指令行,輸入

    npm install mysql

    回車,會生成package.json檔案。
  2. 輸入

    npm install

    回車,會生成package-lock.json檔案。
  3. 此時可在目前項目内的js腳本檔案中使用mysql庫。

5.4.2 示例代碼

/*引入mysql子產品*/
const mysql=require('mysql');
/*配置資料庫連接配接資訊*/
const connection=mysql.createConnection({
    host:"localhost",   /*連接配接位址*/
    user:"root",        /*使用者名*/
    password:"root",    /*密碼*/
    database:"test"     /*被操作的資料庫名*/
});
/*打開連接配接*/
connection.connect();
/*初始化SQL語句*/
let sql="select * from stu where id = ?";
/**
 * 執行SQL
 * 參數1:要執行的sql語句
 * 參數2:sql語句中占位符的内容數組
 * 參數3:回調函數
 * 回調參數1:是否異常,無異常傳回null
 * 回調參數2:執行結果,查詢操作傳回結果集合數組,增删改傳回受影響行數(affectedRows)
 * 回調參數3:資料庫資訊,一般不用
 */
connection.query(sql,[1],function (error,results,field) {
    if(error){
        throw error;
    }
    console.log(results[0].name);
    console.log(field);
});
/*關閉資料庫連接配接*/
connection.end();
           

5.5 UUId子產品

這個子產品我感覺還是使用的比較多的,因為我的個人習慣是插入資料庫的時候使用的id主鍵是一串随機數,是以這個子產品我使用的也比較多,這個還是要看個人習慣,畢竟我現在所寫的東西涉及的資料量過小,效率什麼的還是和自增主鍵差不多,其實還有一個是介于自增主鍵和UUID之間的一個算法,叫雪花算法,這個我沒有具體了解過,隻知道有這麼個東西,等以後有需要了解的時候會更新一篇部落格給大家講解

5.5.1 具體步驟

  1. 在目前項目檔案夾内打開指令行,輸入 `npm install node-uuid 回車,會生成package.json檔案。
  2. 此時可在目前項目内的js腳本檔案中使用uuid庫。

5.5.2 代碼實作

const uuid = require('node-uuid');

let createuuid1 = uuid.v1().replace(/-/g,"").toUpperCase();
let createuuid2 = uuid.v4().replace(/-/g,"").toUpperCase();
console.log(createuuid1);
console.log(createuuid2);
           

這樣就可以生成一個随機的uuid值了

v1和v4的差別

  1. 兩個都是根據時間戳擷取
  2. 如果同樣時間生成的話v1方法生成的UUID相似度會比較高
  3. v4方法生成的UUID更偏向于Java中的UUID工具類,每次生成的值都會有很大的差别,辨識度也比較高,但是會有重複的機率
v1方法生成的UUID截圖
前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品
下面是v4方法生成的uuid截圖
前端學習——NodeJs基礎篇一. NodeJs簡介二. 安裝NodeJs三. NPM簡介四. HelloWorld五. NodeJs子產品

我個人是偏向于使用v4方法的,個人習慣原因,當然使用v1方法也是挺不錯的選擇

以上就是NodeJS的基礎部分,這篇文章裡面僅僅展現了一些基礎的知識,一些比較深的知識沒有涉及到,僅限于入門階段,當然裡面有些觀點可能也有不對的地方,大家看後如果發現什麼觀點有疑問可以多多提出,大家一起學習,共同進步!!!

繼續閱讀