成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

node練手小項目:在線聊天系統(tǒng)

Cristic / 2344人閱讀

摘要:處理程序在的匿名回調(diào)函數(shù)中做請求響應(yīng)的操作,而處理程序仍然是簡單的回復(fù),只是這次是使用對象而已。為了使整個過程非阻塞,會將數(shù)據(jù)拆分成很多小的數(shù)據(jù)塊,然后通過觸發(fā)特定的事件,將這些小數(shù)據(jù)塊傳遞給回調(diào)函數(shù)。

新手node入門,用這個小項目練練手,寫這篇文章也是為了自己鞏固下知識。

先看效果圖:

先是讓用戶輸入名字 get yourself a nickname :)

輸入好了之后進(jìn)入,然后隨便說點(diǎn)什么,


可以多個人在線聊天,


也可以上傳圖片:


更改字體顏色:

制作過程

文件分布:入口文件server.js

本項目的全代碼 https://github.com/FengNianya...(我的github倉庫)

講解:

服務(wù)器server.js
先舉一個例子:我們把我們的服務(wù)器腳本放到一個叫做 start 的函數(shù)里,然后我們會導(dǎo)出這個函數(shù)。

var http = require("http");

function start() {
  function onRequest(request, response) {
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

這樣,我們現(xiàn)在就可以創(chuàng)建我們的主文件 index.js 并在其中啟動我們的HTTP了,雖然服務(wù)器的代碼還在 server.js 中。

創(chuàng)建 index.js 文件并寫入以下內(nèi)容:

var server = require("./server");

server.start();

正如你所看到的,我們可以像使用任何其他的內(nèi)置模塊一樣使用server模塊:請求這個文件并把它指向一個變量,其中已導(dǎo)出的函數(shù)就可以被我們使用了。我們現(xiàn)在可以把我們的應(yīng)用的不同部分放入不同的文件里,并且通過生成模塊的方式把它們連接到一起了。

路由:
對于不同的URL請求,服務(wù)器應(yīng)該有不同的反應(yīng)。

對于一個非常簡單的應(yīng)用來說,你可以直接在回調(diào)函數(shù) onRequest() 中做這件事情。不過就像我說過的,我們應(yīng)該加入一些抽象的元素,讓我們的例子變得更有趣一點(diǎn)兒。

處理不同的HTTP請求在我們的代碼中是一個不同的部分,叫做“路由選擇”——那么,我們接下來就創(chuàng)造一個叫做 路由 的模塊吧。
我們要為路由提供請求的URL和其他需要的GET及POST參數(shù),隨后路由需要根據(jù)這些數(shù)據(jù)來執(zhí)行相應(yīng)的代碼

我們需要的所有數(shù)據(jù)都會包含在request對象中,該對象作為onRequest()回調(diào)函數(shù)的第一個參數(shù)傳遞。但是為了解析這些數(shù)據(jù),我們需要額外的Node.JS模塊,它們分別是url和querystring模塊。
現(xiàn)在我們來給onRequest()函數(shù)加上一些邏輯,用來找出瀏覽器請求的URL路徑:

var http = require("http");
var url = require("url");

function start() {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

應(yīng)用現(xiàn)在可以通過請求的URL路徑來區(qū)別不同請求了--這使我們得以使用路由(還未完成)來將請求以URL路徑為基準(zhǔn)映射到處理程序上。

在我們所要構(gòu)建的應(yīng)用中,這意味著來自/start和/upload的請求可以使用不同的代碼來處理。
router.js:

function route(pathname) {
  console.log("About to route a request for " + pathname);
}

exports.route = route;

如你所見,這段代碼什么也沒干,不過對于現(xiàn)在來說這是應(yīng)該的。在添加更多的邏輯以前,我們先來看看如何把路由和服務(wù)器整合起來。
我們的服務(wù)器應(yīng)當(dāng)知道路由的存在并加以有效利用。我們當(dāng)然可以通過硬編碼的方式將這一依賴項綁定到服務(wù)器上,但是其它語言的編程經(jīng)驗(yàn)告訴我們這會是一件非常痛苦的事,因此我們將使用依賴注入的方式較松散地添加路由模塊
來擴(kuò)展一下服務(wù)器的start()函數(shù),以便將路由函數(shù)作為參數(shù)傳遞過去:

var http = require("http");
var url = require("url");

function start(route) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(pathname);

    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

同時,我們會相應(yīng)擴(kuò)展index.js,使得路由函數(shù)可以被注入到服務(wù)器中:

var server = require("./server");
var router = require("./router");

server.start(router.route);
bash$ node index.js
Request for /foo received.
About to route a request for /foo

你將會看到應(yīng)用輸出相應(yīng)的信息,這表明我們的HTTP服務(wù)器已經(jīng)在使用路由模塊了,并會將請求的路徑傳遞給路由

處理函數(shù)requestHandlers的模塊

并對于每一個請求處理程序,添加一個占位用函數(shù),隨后將這些函數(shù)作為模塊的方法導(dǎo)出:

function start() {
  console.log("Request handler "start" was called.");
}

function upload() {
  console.log("Request handler "upload" was called.");
}

exports.start = start;
exports.upload = upload;

這樣我們就可以把請求處理程序和路由模塊連接起來,讓路由“有路可尋”。
仔細(xì)想想,有一大堆東西,每個都要映射到一個字符串(就是請求的URL)上?似乎關(guān)聯(lián)數(shù)組(associative array)能完美勝任。

引用:不過結(jié)果有點(diǎn)令人失望,JavaScript沒提供關(guān)聯(lián)數(shù)組 -- 也可以說它提供了?事實(shí)上,在JavaScript中,真正能提供此類功能的是它的對象。
在C++或C#中,當(dāng)我們談到對象,指的是類或者結(jié)構(gòu)體的實(shí)例。對象根據(jù)他們實(shí)例化的模板(就是所謂的類),會擁有不同的屬性和方法。但在JavaScript里對象不是這個概念。在JavaScript中,對象就是一個鍵/值對的集合 -- 你可以把JavaScript的對象想象成一個鍵為字符串類型的字典。

好了,最后再回到代碼上來?,F(xiàn)在我們已經(jīng)確定將一系列請求處理程序通過一個對象來傳遞,并且需要使用松耦合的方式將這個對象注入到route()函數(shù)中。

我們先將這個對象引入到主文件index.js中:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.start(router.route, handle);

正如所見,將不同的URL映射到相同的請求處理程序上是很容易的:只要在對象中添加一個鍵為"/"的屬性,對應(yīng)requestHandlers.start即可,這樣我們就可以干凈簡潔地配置/start和/的請求都交由start這一處理程序處理。

在完成了對象的定義后,我們把它作為額外的參數(shù)傳遞給服務(wù)器,為此將server.js修改如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname);

    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

這樣我們就在start()函數(shù)里添加了handle參數(shù),并且把handle對象作為第一個參數(shù)傳遞給了route()回調(diào)函數(shù)。
然后我們相應(yīng)地在route.js文件中修改route()函數(shù):

function route(handle, pathname) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === "function") {
    handle[pathname]();
  } else {
    console.log("No request handler found for " + pathname);
  }
}

exports.route = route;

通過以上代碼,我們首先檢查給定的路徑對應(yīng)的請求處理程序是否存在,如果存在的話直接調(diào)用相應(yīng)的函數(shù)。我們可以用從關(guān)聯(lián)數(shù)組中獲取元素一樣的方式從傳遞的對象中獲取請求處理函數(shù),因此就有了簡潔流暢的形如handle[pathname]();的表達(dá)式

有了這些,我們就把服務(wù)器、路由和請求處理程序在一起了

處理程序與服務(wù)器
我們采用如下這種新的實(shí)現(xiàn)方式:相對采用將內(nèi)容傳遞給服務(wù)器的方式,我們這次采用將服務(wù)器“傳遞”給內(nèi)容的方式。 從實(shí)踐角度來說,就是將response對象(從服務(wù)器的回調(diào)函數(shù)onRequest()獲取)通過請求路由傳遞給請求處理程序。 隨后,處理程序就可以采用該對象上的函數(shù)來對請求作出響應(yīng)。

原理就是如此,接下來讓我們來一步步實(shí)現(xiàn)這種方案。

先從server.js開始:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname, response);
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

相對此前從route()函數(shù)獲取返回值的做法,這次我們將response對象作為第三個參數(shù)傳遞給route()函數(shù),并且,我們將onRequest()處理程序中所有有關(guān)response的函數(shù)調(diào)都移除,因?yàn)槲覀兿M@部分工作讓route()函數(shù)來完成。

下面就來看看我們的router.js:

function route(handle, pathname, response) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === "function") {
    handle[pathname](response);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;

同樣的模式:相對此前從請求處理程序中獲取返回值,這次取而代之的是直接傳遞response對象。

如果沒有對應(yīng)的請求處理器處理,我們就直接返回“404”錯誤。

最后,我們將requestHandler.js修改為如下形式:

var exec = require("child_process").exec;

function start(response) {
  console.log("Request handler "start" was called.");

  exec("ls -lah", function (error, stdout, stderr) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write(stdout);
    response.end();
  });
}

function upload(response) {
  console.log("Request handler "upload" was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello Upload");
  response.end();
}

exports.start = start;
exports.upload = upload;

我們的處理程序函數(shù)需要接收response參數(shù),為了對請求作出直接的響應(yīng)。

start處理程序在exec()的匿名回調(diào)函數(shù)中做請求響應(yīng)的操作,而upload處理程序仍然是簡單的回復(fù)“Hello World”,只是這次是使用response對象而已。

這時再次我們啟動應(yīng)用(node index.js),一切都會工作的很好。

處理POST請求
考慮這樣一個簡單的例子:我們顯示一個文本區(qū)(textarea)供用戶輸入內(nèi)容,然后通過POST請求提交給服務(wù)器。最后,服務(wù)器接受到請求,通過處理程序?qū)⑤斎氲膬?nèi)容展示到瀏覽器中。

/start請求處理程序用于生成帶文本區(qū)的表單,因此,我們將requestHandlers.js修改為如下形式:

function start(response) {
  console.log("Request handler "start" was called.");

  var body = ""+
    ""+
    ""+
    ""+
    ""+
    "
"+ ""+ ""+ "
"+ ""+ ""; response.writeHead(200, {"Content-Type": "text/html"}); response.write(body); response.end(); } function upload(response) { console.log("Request handler "upload" was called."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello Upload"); response.end(); } exports.start = start; exports.upload = upload;

這里采用非阻塞方式處理是明智的,因?yàn)镻OST請求一般都比較“重” —— 用戶可能會輸入大量的內(nèi)容。用阻塞的方式處理大數(shù)據(jù)量的請求必然會導(dǎo)致用戶操作的阻塞。

為了使整個過程非阻塞,Node.js會將POST數(shù)據(jù)拆分成很多小的數(shù)據(jù)塊,然后通過觸發(fā)特定的事件,將這些小數(shù)據(jù)塊傳遞給回調(diào)函數(shù)。這里的特定的事件有data事件(表示新的小數(shù)據(jù)塊到達(dá)了)以及end事件(表示所有的數(shù)據(jù)都已經(jīng)接收完畢)。

我們需要告訴Node.js當(dāng)這些事件觸發(fā)的時候,回調(diào)哪些函數(shù)。怎么告訴呢? 我們通過在request對象上注冊監(jiān)聽器(listener) 來實(shí)現(xiàn)。這里的request對象是每次接收到HTTP請求時候,都會把該對象傳遞給onRequest回調(diào)函數(shù)。
如下所示:

request.addListener("data", function(chunk) {
  // called when a new chunk of data was received
});

request.addListener("end", function() {
  // called when all chunks of data have been received
});

問題來了,這部分邏輯寫在哪里呢? 我們現(xiàn)在只是在服務(wù)器中獲取到了request對象 —— 我們并沒有像之前response對象那樣,把 request 對象傳遞給請求路由和請求處理程序。

在我看來,獲取所有來自請求的數(shù)據(jù),然后將這些數(shù)據(jù)給應(yīng)用層處理,應(yīng)該是HTTP服務(wù)器要做的事情。因此,我建議,我們直接在服務(wù)器中處理POST數(shù)據(jù),然后將最終的數(shù)據(jù)傳遞給請求路由和請求處理器,讓他們來進(jìn)行進(jìn)一步的處理。

因此,實(shí)現(xiàn)思路就是: 將data和end事件的回調(diào)函數(shù)直接放在服務(wù)器中,在data事件回調(diào)中收集所有的POST數(shù)據(jù),當(dāng)接收到所有數(shù)據(jù),觸發(fā)end事件后,其回調(diào)函數(shù)調(diào)用請求路由,并將數(shù)據(jù)傳遞給它,然后,請求路由再將該數(shù)據(jù)傳遞給請求處理程序。

還等什么,馬上來實(shí)現(xiàn)。先從server.js開始:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var postData = "";
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    request.setEncoding("utf8");

    request.addListener("data", function(postDataChunk) {
      postData += postDataChunk;
      console.log("Received POST data chunk ""+
      postDataChunk + "".");
    });

    request.addListener("end", function() {
      route(handle, pathname, response, postData);
    });

  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

上述代碼做了三件事情: 首先,我們設(shè)置了接收數(shù)據(jù)的編碼格式為UTF-8,然后注冊了“data”事件的監(jiān)聽器,用于收集每次接收到的新數(shù)據(jù)塊,并將其賦值給postData 變量,最后,我們將請求路由的調(diào)用移到end事件處理程序中,以確保它只會當(dāng)所有數(shù)據(jù)接收完畢后才觸發(fā),并且只觸發(fā)一次。我們同時還把POST數(shù)據(jù)傳遞給請求路由,因?yàn)檫@些數(shù)據(jù),請求處理程序會用到。

上述代碼在每個數(shù)據(jù)塊到達(dá)的時候輸出了日志,這對于最終生產(chǎn)環(huán)境來說,是很不好的(數(shù)據(jù)量可能會很大,還記得吧?),但是,在開發(fā)階段是很有用的,有助于讓我們看到發(fā)生了什么。

我建議可以嘗試下,嘗試著去輸入一小段文本,以及大段內(nèi)容,當(dāng)大段內(nèi)容的時候,就會發(fā)現(xiàn)data事件會觸發(fā)多次。
再來點(diǎn)酷的。我們接下來在/upload頁面,展示用戶輸入的內(nèi)容。要實(shí)現(xiàn)該功能,我們需要將postData傳遞給請求處理程序,修改router.js為如下形式:

function route(handle, pathname, response, postData) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === "function") {
    handle[pathname](response, postData);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;

然后,在requestHandlers.js中,我們將數(shù)據(jù)包含在對upload請求的響應(yīng)中:

function start(response, postData) {
  console.log("Request handler "start" was called.");

  var body = ""+
    ""+
    ""+
    ""+
    ""+
    "
"+ ""+ ""+ "
"+ ""+ ""; response.writeHead(200, {"Content-Type": "text/html"}); response.write(body); response.end(); } function upload(response, postData) { console.log("Request handler "upload" was called."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("You"ve sent: " + postData); response.end(); } exports.start = start; exports.upload = upload;

好了,我們現(xiàn)在可以接收POST數(shù)據(jù)并在請求處理程序中處理該數(shù)據(jù)了。

我們最后要做的是: 當(dāng)前我們是把請求的整個消息體傳遞給了請求路由和請求處理程序。我們應(yīng)該只把POST數(shù)據(jù)中,我們感興趣的部分傳遞給請求路由和請求處理程序。在我們這個例子中,我們感興趣的其實(shí)只是text字段。

我們可以使用此前介紹過的querystring模塊來實(shí)現(xiàn):

var querystring = require("querystring");

function start(response, postData) {
  console.log("Request handler "start" was called.");

  var body = ""+
    ""+
    ""+
    ""+
    ""+
    "
"+ ""+ ""+ "
"+ ""+ ""; response.writeHead(200, {"Content-Type": "text/html"}); response.write(body); response.end(); } function upload(response, postData) { console.log("Request handler "upload" was called."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("You"ve sent the text: "+ querystring.parse(postData).text); response.end(); } exports.start = start; exports.upload = upload;

處理文件上傳
這里我們要用到的外部模塊是Felix Geisend?rfer開發(fā)的node-formidable模塊。它對解析上傳的文件數(shù)據(jù)做了很好的抽象。 其實(shí)說白了,處理文件上傳“就是”處理POST數(shù)據(jù) —— 但是,麻煩的是在具體的處理細(xì)節(jié),所以,這里采用現(xiàn)成的方案更合適點(diǎn)。

使用該模塊,首先需要安裝該模塊。Node.js有它自己的包管理器,叫NPM。它可以讓安裝Node.js的外部模塊變得非常方便。通過如下一條命令就可以完成該模塊的安裝:

npm install formidable
npm info build Success: [email protected]
npm ok
var querystring = require("querystring"),
    fs = require("fs");

function start(response, postData) {
  console.log("Request handler "start" was called.");

  var body = ""+
    ""+
    ""+
    ""+
    ""+
    "
"+ ""+ ""+ "
"+ ""+ ""; response.writeHead(200, {"Content-Type": "text/html"}); response.write(body); response.end(); } function upload(response, postData) { console.log("Request handler "upload" was called."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("You"ve sent the text: "+ querystring.parse(postData).text); response.end(); } function show(response, postData) { console.log("Request handler "show" was called."); fs.readFile("/tmp/test.png", "binary", function(error, file) { if(error) { response.writeHead(500, {"Content-Type": "text/plain"}); response.write(error + " "); response.end(); } else { response.writeHead(200, {"Content-Type": "image/png"}); response.write(file, "binary"); response.end(); } }); } exports.start = start; exports.upload = upload; exports.show = show;

我們還需要將這新的請求處理程序,添加到index.js中的路由映射表中:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;

server.start(router.route, handle);

好,最后我們要的就是:

在/start表單中添加一個文件上傳元素
將node-formidable整合到我們的upload請求處理程序中,用于將上傳的圖片保存到/tmp/test.png
將上傳的圖片內(nèi)嵌到/uploadURL輸出的HTML中
需要在upload處理程序中對上傳的文件進(jìn)行處理,這樣的話,我們就需要將request對象傳遞給node-formidable的form.parse函數(shù)。

但是,我們有的只是response對象和postData數(shù)組??礃幼樱覀冎荒懿坏貌粚equest對象從服務(wù)器開始一路通過請求路由,再傳遞給請求處理程序。 或許還有更好的方案,但是,不管怎么說,目前這樣做可以滿足我們的需求。

到這里,我們可以將postData從服務(wù)器以及請求處理程序中移除了 —— 一方面,對于我們處理文件上傳來說已經(jīng)不需要了,另外一方面,它甚至可能會引發(fā)這樣一個問題: 我們已經(jīng)“消耗”了request對象中的數(shù)據(jù),這意味著,對于form.parse來說,當(dāng)它想要獲取數(shù)據(jù)的時候就什么也獲取不到了。(因?yàn)镹ode.js不會對數(shù)據(jù)做緩存)

我們從server.js開始 —— 移除對postData的處理以及request.setEncoding (這部分node-formidable自身會處理),轉(zhuǎn)而采用將request對象傳遞給請求路由的方式:

    var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    route(handle, pathname, response, request);
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

接下來是 router.js —— 我們不再需要傳遞postData了,這次要傳遞request對象:

function route(handle, pathname, response, request) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === "function") {
    handle[pathname](response, request);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/html"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;
還沒寫完,有空繼續(xù)更新,也可以看下載個
 》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/89579.html

相關(guān)文章

  • nodejs練手爬蟲+API測試

    摘要:知乎日報代理首先感謝提供的分析使用詳情請參考他提供的參數(shù)和地址代理轉(zhuǎn)發(fā)的使用為前綴進(jìn)入代理路由啟動界面圖像獲取后為圖像分辨率,接受任意的格式,為任意非負(fù)整數(shù),返回值均相同返回值示例最新消息等具體參考提供的分析中的使用方式以及參數(shù)含義。 項目說明 這是一個基于express的node后端API服務(wù),當(dāng)時只是想抓取字幕組網(wǎng)站的下載資源,以備以后通過nas的方式去自動下載關(guān)注的美劇。不過后來...

    bigdevil_s 評論0 收藏0
  • 基于 Vue2+Node+mongoDB 的前后端分離全棧練手項目

    摘要:本文源碼簡介之前剛?cè)腴T并做好了一個簡而全的純?nèi)彝暗捻椖?,?shù)據(jù)都是本地模擬請求的詳情請移步這里為了真正做到數(shù)據(jù)庫的真實(shí)存取,于是又開始入門了并以此來為之前的頁面寫后臺數(shù)據(jù)接口。 本文源碼:Github 簡介: 之前剛?cè)腴Tvue并做好了一個簡而全的純vue2全家桶的項目,數(shù)據(jù)都是本地 json 模擬請求的;詳情請移步這里:vue-proj-demo 為了真正做到數(shù)據(jù)庫的真實(shí)存取,于是又...

    jay_tian 評論0 收藏0
  • 全棧最后一公里 - Node.js 項目的線上服務(wù)器部署與發(fā)布

    摘要:沒有耐心閱讀的同學(xué),可以直接前往學(xué)習(xí)全棧最后一公里。我下面會羅列一些,我自己錄制過的一些項目,或者其他的我覺得可以按照這個路線繼續(xù)深入學(xué)習(xí)的項目資源。 showImg(https://segmentfault.com/img/bVMlke?w=833&h=410); 本文技術(shù)軟文,閱讀需謹(jǐn)慎,長約 7000 字,通讀需 5 分鐘 大家好,我是 Scott,本文通過提供給大家學(xué)習(xí)的方法,...

    Nosee 評論0 收藏0
  • vue+socket.io+express+mongodb 實(shí)現(xiàn)簡易多房間在線群聊

    摘要:項目簡介主要是通過做一個多人在線多房間群聊的小項目來練手全棧技術(shù)的結(jié)合運(yùn)用。編譯運(yùn)行開啟服務(wù),新建命令行窗口啟動服務(wù)端,新建命令行窗口啟動前端頁面然后在瀏覽器多個窗口打開,注冊不同賬號并登錄即可進(jìn)行多用戶多房間在線聊天。 項目簡介 主要是通過做一個多人在線多房間群聊的小項目、來練手全棧技術(shù)的結(jié)合運(yùn)用。 項目源碼:chat-vue-node 主要技術(shù): vue2全家桶 + socket....

    android_c 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<