Vue+element+Nodejs學習記錄(1)

目前的打算是前端用Vue+element,後端用Nodejs的Express框架,實現一個展示頁面和後臺管理頁面。打算記錄學習過程。

推薦兩個教程:
https://www.cnblogs.com/xifengxiaoma/tag/element/
https://juejin.im/post/59097cd7a22b9d0065fb61d2#heading-1
https://panjiachen.github.io/vue-element-admin-site/zh/guide/
https://blog.csdn.net/sps900608/article/category/7482283/1

1.Nodejs介紹

JS和Nodejs

1、ES 定義了語法規則,JS和Nodejs必須遵守
2、js js=ES+web API(DOM,BOM,事件綁定,ajax)
3、node.js node.js=ES+nodejs API(處理http,處理文件等) ,兩者結合,可完成server端的任何操作

Commonjs和ES6模塊使用規範

//Commonjs

//math.js
let add=(x,y)=>{
    return x+y;
}
let sub=(x,y)=>{
    return x-y;
}

module.exports={
    add:add,
    sub:sub
};

let math=require('./math');
let test=math.add(3,3);
console.log(test);

//ES6模塊化

//lib.js
let bar=function(){
    console.log('this is bar funciton');
};

let foo=function(){
    console.log('this is foo function');
};

export {bar,foo}

 //加載 lib.js文件
 import {bar,foo,test,obj} from './lib'
 
 foo();//this is foo function

server開發和前端開發的區別

環境思維工具的區別,而不是語言的區別

1.服務的穩定性:server端可能會遭受各種攻擊和誤操作,單個客戶端可以意外掛掉,但是服務端不能
2.考慮內存和CPU(優化和擴展):客戶端獨佔一個瀏覽器,內存和CPU都不是問題,但是 server 端要承載很多請求,CPU和內存都是稀缺資源
3.日誌記錄:前端也會參與寫日誌,但是隻是日誌的發起方,不關心後續;server端要記錄日誌,存儲日誌,分析日誌
4.安全: server端要隨時準備接受各種惡意攻擊(如越權操作,數據庫攻擊等),前端則少很多
5.集羣和服務拆分:流量擴大,解決機器的負荷

2.HTTP請求(get和post)

HTTP請求解析過程 (簡單概括)

1.域名解析
用戶輸入網址,由域名系統DNS解析輸入的網址;

2.TCP的3次握手
通過域名解析出的IP地址來向web服務器發起TCP連接請求,如果3次握手通過,則與web服務端建立了可靠的連接;

3.發送http請求
web客戶端向web服務端發送請求;

4.接收http響應
web客戶端接收來自web服務端的響應,包含各種根據請求反饋的數據;

5.web客戶端(瀏覽器)解釋響應
最後由瀏覽器解析響應裏的數據,即HTML代碼,以及HTML代碼中請求的資源,然後由瀏覽器呈現給用戶。

get請求和post請求

get請求:
1.get請求,即客戶端要向server端獲取數據,如查詢博客列表
2.通過querystring來傳遞數據,如a.html?a=100&b=200
3.瀏覽器直接訪問,就發送get請求

const server = http.createServer((req,res) => {

	console.log(req.method);   //GET
	const url = req.url;   //獲取請求的完整 url

	//querystring.parse("name=whitemu&sex=man&sex=women");
	/*
	return:
	 { name: 'whitemu', sex: [ 'man', 'women' ] }
	*/
	req.query = querystring.parse(url.split('?')[1]);   //解析 querystring

	res.end(JSON.stringfy(req.query));//將對象轉換成字符串,res.end返回一個字符串

})

附註:
querystring.parse將字符串轉成對象,其實就是把url上帶的參數串轉成數組對象。

JSON.stringify() 方法是將一個JavaScript值(對象或者數組)轉換爲一個 JSON字符串,JSON.parse() 方法用來解析JSON字符串,構造由字符串描述的JavaScript值或對象。

//JSON.parse()
var json = '{"result":true, "count":42}';
obj = JSON.parse(json);
console.log(obj);
console.log(obj.result);

> { result: true, count: 42 }
> true

//JSON.stringify()
JSON.stringify({});                        // '{}'
JSON.stringify(true);                      // 'true'
JSON.stringify("foo");                     // '"foo"'
JSON.stringify([1, "false", false]);       // '[1,"false",false]'
JSON.stringify({ x: 5 });                  // '{"x":5}'

參考文章:
https://blog.csdn.net/qq_34645412/article/details/80087829
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

post請求:

1.post請求,即客戶端要向服務端傳遞數據,如新建博客
2.通過post data傳遞數據
3.瀏覽器無法直接模型,需要手寫j,或者通過postman

post接收數據是通過數據流的方式,數據流就是所謂的stream。

post方式發送的數據,可大可小。小的話還好,數據量大的時候,不闊能一次性接收,而是分流接收
每次接收的到數據都會觸發 req.on(‘data’,chunk=>{}),當接收完之後就會觸發req.end 事件

const server = http.createServer((req,res) => {

	if(req.method === 'POST'){   //POST
		//數據格式
		console.log('content-type',req.headers['content-type']);
		//接收數據
		let postData = ""
		req.on('data',chunk => {
			postData += chunk.toString();
		})
		req.on('end', () => {
			console.log(postData);
			res.end('hello world')
		})
	}
})

get和post

const http = require('http')
const querystring = require('querystring')

const server = http.createServer((req, res) => {
    const method = req.method
    const url = req.url
    const path = url.split('?')[0]
    const query = querystring.parse(url.split('?')[1])

    // 設置返回格式爲 JSON
    res.setHeader('Content-type', 'application/json')

    // 返回的數據
    const resData = {
        method,
        url,
        path,
        query
    }

    // 返回
    if (method === 'GET') {
        res.end(
            JSON.stringify(resData)
        )
    }
    if (method === 'POST') {
        let postData = ''
        req.on('data', chunk => {
            postData += chunk.toString()
        })
        req.on('end', () => {
            resData.postData = postData
            console.log(postData)
            // 返回
            res.end(
                JSON.stringify(resData)
            )
        })
    }
})

server.listen(8000)
console.log('OK')

3.搭建開發環境

1.初始化 npm 環境: npm init -y
2. package.json 的 main 值默認 index.js 爲主程序
3. bin 目錄裏面一般爲可執行文件
4. nodemon: 檢測文件變化,自動重啓 node
5.cross-env: 設置環境
5. 安裝 nodemon 和 cross-env: npm install nodemon cross-env --save-dev --registry=https://registry.npm.taobao.org
6. process.env.NODE_ENV: 獲取當前運行環境

nodemon監測文件變化,自動重啓Node
cross-env設置環境變量,之後做環境區分使用,運行跨平臺設置和使用環境變量的腳本
process是node的全局變量,process.env.NODE_ENV可以獲取當前運行環境

cross-env介紹

這個小插件主要解決 windows 下 無法設置 NODE_ENV=development 這個東西. 因爲程序可以根據 NODE的環境變量,做出不同選擇,進行不同的設置.

這個在 linux 下是可以設置的,但在 windows 下不行

package.json配置

//process是node提供的全局變量。
dev: cross-env NODE_ENV=dev nodemon ./bin/www.js  //開發環境
prd: cross-env NODE_ENV=production nodemon ./bin/www.js  //生產環境

參考文章:
http://elickzhao.github.io/2017/06/nodejs%20%E7%9A%84%20cross-env%20%E7%9A%84%E4%BD%BF%E7%94%A8%E5%8F%8A%E4%BB%8B%E7%BB%8D/
https://segmentfault.com/a/1190000005811347

4.接口設計

在這裏插入圖片描述
app.js

//引用和處理路由(handleBlogRouter和handleUserRouter)
const handleBlogRouter = require('./src/router/blog')
const handleUserRouter = require('./src/router/user')

const serverHandle = (req,res) => {

	//設置返回格式 JSON
	res.setHeader('Content-type','application/json')

	//處理blog路由
	const blogData = handleBlogRouter(req,res)
	if(blogData){
		res.end(
			JSON.stringify(blogData)
		)
		return
	}

	//處理user路由
	const userData = handleUserRouter(req,res)
	if(userData){
		res.end(
			JSON.stringify(userData)
		)
		return
	}

	//未命中路由,返回404
	res.writeHead(404,{"Content-type":"text/plain"})
	res.write("404 Not Found\n")
	res.end()

}

module.exports = serverHandle

src/router/blog.js

const handleBlogRouter = (req,res)=> {

	const method = req.method //GET POST
	const url = req.url //獲取url
	const path = url.split('?')[0] 

	//獲取博客列表
	if (method === 'GET' && path === '/api/blog/list') {

		return {
			msg : '這是獲取博客列表的接口'
		}

	}

	//獲取博客詳情
	if(method === 'POST' && path === '/api/blog/detail'){

		return {
			msg : '這是獲取博客詳情的接口'
		}

	}

	//新建一篇博客
	if(method === 'POST' && path === '/api/blog/new'){

		return {
			msg : '這是新建博客詳情的接口'
		}

	}

	//更新一篇博客
	if(method === 'POST' && path === '/api/blog/update'){

		return {
			msg : '這是更新博客詳情的接口'
		}

	}

	//一篇博客
	if(method === 'POST' && path === '/api/blog/del'){

		return {
			msg : '這是刪除一篇博客的接口'
		}

	}

}

module.exports = handleBlogRouter

src/router/user.js

const handleUserRouter = (req,res)=> {

	const method = req.method //GET POST
	const url = req.url //獲取url
	const path = url.split('?')[0] 

	//獲取博客列表
	if (method === 'POST' && path === '/api/user/login') {

		return {
			msg : '這是登陸的接口'
		}

	}

}

module.exports = handleUserRouter

雖然路由沒有寫具體處理代碼,但是展示了路由的使用和路由引用和處理,基本的路由創建,路由內容和路由使用有個框架,下一步就是具體代碼編寫和邏輯進一步劃分。

5.博客系統的分層

上面只是把路由分離出來,我們要如何進一步劃分代碼見邏輯呢?

第一層是bin/www.js,這一層完全是createServer的邏輯。這個邏輯跟外面的業務代碼沒有任何關係。(關於數據的處理,使用回調函數,放在了app.js裏面)
第二層是app.js,這是一個系統中關於http的基本設置(比如:設置返回格式JSON、獲取path、解析jquery處理相關模塊的路由和設置404情況),跟業務代碼關係也不大。(只是負責調用路由,關於路由的具體邏輯放在router中)
第三層router,第二層中引用的路由,所以第三層就是路由。路由就有涉及到一些業務代碼,有了會返回給請求一個正確的格式數據。這個路由會去處理一些數據,返回正確的格式。具體數據的處理它不用管,它只負責路由相關的事情。
第四層controller,處理和管理數據,到了controller裏面就不用關心request和response、path、query等東西,就只關心數據。然後返回數據,數據之後怎麼處理,controller是不管的。
第五層model

附註
第一層和第二層中的www.js 和 app.js 的目的不一樣,第一個是啓動服務,第二個是加載註冊各種業務組件,兩者應該分離,符合設計原則。

第一層(創建服務器)、第二層(系統基本設置)、第三層(路由)都屬於 MVC 的C ,即 controller ,MVC 是一個大概念上的分層,不代表每個部分不能再分層。如果項目再複雜,C 和 M 之間可能還要加一個 services 層,如 egg.js 的目錄,就有 services 層。

router層負責拿參數
controller層負責數據的計算 最終拿到數據
model層負責 生成一個實例 將data message errno 返回給前端

6.Nodejs讀取文件

const fs = require('fs')
const path = require('path')

//resolve可以通過拼接多個步驟的方式把文件名拼出來,__dirname是指當前目錄
const fullFileName = path.resolve(__dirname,'files','a.json')

fs.readFile(fullFileName,(err,data) => {

	if(err){
		console.error(err)
		return
	}
	//fs.readFile 讀出來的data數據是二進制的流文件,所以要經過toString轉換
	console.log(data.toString())

})

我們要注意resolve和toString的使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章