文章目录
Node.js 起步
-
Node.js 是一个服务端的语言
-
服务端的语言与前端不一样,前端只有H5,CSS,JS以及以他为基础的其他语言,但是服务端有很多语言都可以实现H5这样最基础的功能,他们之间是并列关系,没有依赖,例如Java,PHP,Python,Ruby,.Net,Nodejs
-
使用Node.js的原因是可以使用js语言,对前端友好
-
Node.js是什么
-
是一个JS运行时环境(Runtime lib)而不是一个库,不是一个框架,不是一个语言,(可以理解他是和一个浏览器一样的东西,但是有点不一样)
-
浏览器中的JS是什么
- 基础语法 ECMAScript
- DOM
- BOM
-
Node.js中的JS是什么
- 没有BOM,DOM(因为服务端不处理页面)
- 基础语法 ECMAScript
- 服务器级别的API(文件读写,网络服务构建,http服务…)
-
-
是一个事件驱动,非阻塞IO模型(异步),高效轻量
-
使用npm生态系统,也是最大的开源生态系统
-
构建在v8引擎是上的
-
-
Nodejs可以做什么
- Web后台
- 命令行工具(例如: hexo,gulp…)
- 接口服务器
简单程序
直接创建js文件写就可以了,不需要依赖html文件,之后使用node xx.js执行文件
写出hello world
var foo='hello world'
console.log(foo);
之后尝试服务端的文件读写,注意浏览器的HTML是不支持文件读写的
// fs是file-system的缩写,就是文件系统的意思
// 在Node中如果想要使用文件io那必须引入fs这个模块
// fs模块为所有的文本操作提供了相关的api
var fs=require("fs");
// 其中的readFile是用来读取文件的,第一个是地址,第二个是回调函数,回调接受两个参数,error和data
// - error表示文件读取是否有错误,有错是error对象,没错的null
// - data是读取到的数据,有错是null,没错是16进制结果,需要toString才能看
fs.readFile("./test",function(error,data){
if(!error)
console.log(data.toString());
else
console.log("ERROR!!\n"+error)
});
// tst文件不存在
fs.readFile("./tst",function(error,data){
if(!error)
console.log(data.toString());
else
console.log("ERROR!!\n"+error)
});
// 参数为 路径 内容 回调函数(接受error)
fs.writeFile("./out","测试文本",function(error){
if(error)
console.log("文件写入失败");
})
// 文件名有非法字符 写入失败
fs.writeFile("./o/*-ut","测试文本",function(error){
if(error)
console.log("文件写入失败"+error);
})
最简单的http服务
需要核心模块http
// 加载http核心模块
var http = require('http');
// 使用http.creatServer创建一个web服务器
// 返回一个server实例
var server = http.createServer();
// 发请求 收请求 处理请求 发生相应
// 注册request请求时间,受到request请求之后就会执行回调函数
server.on("request",function(){
console.log("受到客户端请求");
})
// 绑定3000端口,启动服务器
server.listen(3000,function(){
console.log("服务器启动成功");
});
响应请求
var http = require('http');
var server = http.createServer();
//request的回调函数要接受两个函数
// - Request 请求对象
// 获取客户端的请求信息,例如路径
// - Reponse 相应对象
// 响应对象可以用来给客户端发送相应消息
server.on("request",function(request,response){
// 输出访问路径的地址 127.0.0.1:3000/a 得到的是/a
console.log("受到客户端请求, 请求路径是"+request.url);
// response.write可以用来发送相应
// write可以用多次但是一定要用end来结束否则客户端会一直接受,end之后不能再发请求
response.write("hello");
response.write("123456");
response.end();
})
server.listen(3000,function(){
console.log("服务器启动成功");
});
p.s. 浏览器在访问的时候会有一个默认请求favicon.ico,获取图标不用管
不同路径不同请求
var http = require('http');
var server = http.createServer();
server.on("request",function(request,response){
var value=""
var obj=[{
title:123,
name:456,
},{
title:45,
name:45,
},{
title:23,
name:4,
}];
switch (request.url) {
case "/":value="index";break;
case "/log":value="登陆";break;
case "/reg":value="注册";break;
default:value="错误";break;
}
response.write("收到请求,进入"+value+"页面");
// 注意相应内容只能是二进制文件或者是字符串,不支持JSON对象,数组....
response.write(JSON.stringify(obj));
response.end();
})
server.listen(3000,function(){
console.log("服务器启动成功");
});
获取服务器端口与客户端端口号
server.on("request",function(request,response){
console.log("服务端口:"+request.socket.localPort+"客户端端口"+request.socket.remotePort);
}
中文乱码的问题
node服务器默认是发送utf8的数据,但是浏览器不知道,于是按照操作系统默认编码解析,于是服务器要告诉浏览器是用的utf8,方法是
rep.setHeader('Content-Type',"text/plain;charset=utf-8")
Node中的js
- ECMAScript
- 没有DOM,BOM
- 核心模块
- Node为JS提供了服务器级别的API,他们都被包装到了一个具名的核心模块中了,例如
fs文件系统,httphttp模块,path路径模块,os操作系统模块 - 以后一说他是核心模块就直接
var XXX=require("YY")XX命名不强制最好与YY相同
- Node为JS提供了服务器级别的API,他们都被包装到了一个具名的核心模块中了,例如
- 第三方模块
- 自定义模块
简单模块化
两个方法: require用来加载export用来导出
require 是一个方法
他的作用是加载模块的
模块有三种
- 具名的核心模块,例如 fs, http
- 用户自己编写的文件模块(require的时候./不能省略否则就成核心模块了,可以不写.js)
1.js
console.log("开始执行1");
var mod2=require("./2.js")
console.log("结束执行1");
2.js
console.log("外部文件加载好了")
- 在node中,没有全局作用域,只有模块作用域,也就是变量只能在本文件内部使用
- require之后会自动执行内部的代码然后获取文件的接口对象
- 如果不仅想要执行子模块代码,还想使用接口对象中的内容需要
- 将方法实例化成本模块中的一个对象
- 将需要暴露的对象作为接口对象导出
1.js 续
console.log(mod2.foo)
console.log(mod2.plus(1,1.2));
2.js 续
exports.foo="hello";
exports.plus=function(a,b){
return a+b;
}
响应内容类型Content-Type
rep.setHeader("Content-Type","text/plain;charset=utf-8");
注意双引号是引到哪里
对与HTML代码的设置
以上是针对纯文本的,尝试以下设置
var http=require("http");
var server=http.createServer();
server.on("request",function(req,rep){
rep.write("<p>123<a href="javascript:;">456</a></p>");
rep.write("<p>中文<a href="javascript:;">测试</a></p>");
rep.end();
})
server.listen(3000,function(){
console.log("node start...");
})
- 发现123456显示正常,并没有显示标签,可以看到network受到的包是有标签的,是浏览器进行了渲染导致用户看不到标签
- 发现中文显示失败,这是因为没有设置utf-8
尝试设置
var http=require("http");
var server=http.createServer();
server.on("request",function(req,rep){
rep.setHeader("Content-Type","text/plain;charset=utf-8");
rep.write("<p>123<a href="javascript:;">456</a></p>");
rep.write("<p>中文<a href="javascript:;">测试</a></p>");
rep.end();
})
server.listen(3000,function(){
console.log("node start...");
})
发现 中文显示正常,但是标签被显示了,这是因为node明确的告诉了浏览器这是文本,不让浏览器解析,解决方法是把plain改为html
var http=require("http");
var server=http.createServer();
server.on("request",function(req,rep){
rep.setHeader("Content-Type","text/html;charset=utf-8");
rep.write("<p>123<a href="javascript:;">456</a></p>");
rep.write("<p>中文<a href="javascript:;">测试</a></p>");
rep.end();
})
server.listen(3000,function(){
console.log("node start...");
})
中文与标签正常显示
注意每一次发送响应只能设置一次Content-Type,每次end后不得再次write
其他类型的Content-Type
- html文件
var http=require("http");
var fs=require("fs");
const {
report } = require("process");
var server=http.createServer();
server.on("request",function(req,rop){
rop.setHeader("Content-Type","text/html;charset=utf-8")
fs.readFile("./index.html",function(error,data){
if(error)
rop.write("ERROR");
else
rop.write(data);
});
rop.write("123");
rop.end();
})
server.listen(3000,function(){
console.log("working...");
})
注意,有问题,只能看到123因为回调函数是异步模块,当读取到回调函数的时候会将他放到事件队列等待,执行主线程,于是就读取了rop.write("123");然后马上就是rop.end等主代码结束,才打开时间队列循环,发送请求,但是迟了,早就end了!!!,如何验证??换成如下代码,等读到setTimeout(rop.end,10000);开始分线程计时,读取事件队列,之后10s后发送end,源文件显示了,同时可以看到是先有123后有HTML代码!!
server.on("request",function(req,rop){
rop.setHeader("Content-Type","text/html;charset=utf-8")
fs.readFile("./index.html",function(error,data){
if(error)
rop.write("ERROR");
else
rop.write(data);
});
rop.write("123");
setTimeout(rop.end,10000);
})
所以,最好的办法是
var http=require("http");
var fs=require("fs");
const {
report } = require("process");
var server=http.createServer();
server.on("request",function(req,rop){
rop.setHeader("Content-Type","text/html;charset=utf-8")
fs.readFile("./index.html",function(error,data){
if(error)
rop.end("ERROR");
else
rop.end(data);
});
})
server.listen(3000,function(){
console.log("working...");
})
终止必须在异步模块里面
- png
// png 图片就不用指定编码了 一般只有字符数据指定编码
rop.setHeader("Content-Type","image/png");
fs.readFile("./3.png",function(error,data){
if(error)
rop.end("ERROR");
else
rop.end(data);
});
- 其他类型的Content-Type
- 媒体格式
- text/html : HTML格式
- text/plain :纯文本格式
- text/xml : XML格式
- image/gif :gif图片格式
- image/jpeg :jpg图片格式
- image/png:png图片格式
- 以application开头的媒体格式类型:
- application/xhtml+xml :XHTML格式
- application/xml : XML数据格式
- application/atom+xml :Atom XML聚合格式
- application/json : JSON数据格式
- application/pdf :pdf格式
- application/msword : Word文档格式
- application/octet-stream : 二进制流数据(如常见的文件下载)
- application/x-www-form-urlencoded :
<form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
- 更多(https://tool.oschina.net/commons)[https://tool.oschina.net/commons]
- 媒体格式
实现一些apach功能
实现目录浏览功能
- 输入地址访问部分文件
var http=require("http");
var fs=require("fs");
var server=http.createServer();
server.on("request",function(req,res){
rep.setHeader("Content-Type","text/plain;charset=utf-8")
var reg=new RegExp("^\/file\/","i");
if(reg.test(req.url)){
fs.readFile(req.url.replace(reg,".\/"),function(error,data){
if(error){
res.end("ERROR REQ");
console.log(error);
}else{
res.end(data);
}
});
}else{
res.end("welcom");
}
});
server.listen(3000,function(){
console.log("working...");
})
输入网址访问文件目录
需求1 显示指定文件夹下文件目录
需要使用文件目录那一定是fs模块,查API得到fs.readdir("PATH",function(error,files))files是文件名数组(注意两个d都没大写)
var fs=require("fs");
fs.readdir("../01/",function(error,files){
if(error)
console.log(error);
else
console.log(files);
});
需求2 动态显示
当然我们可以使用字符串替换暴力实现
<!DOCTYPE html>
<html dir="ltr" lang="zh">
<head>
<meta charset="utf-8">
<style>
h1 {
border-bottom: 1px solid #c0c0c0;
margin-bottom: 10px;
padding-bottom: 10px;
white-space: nowrap;
}
table {
border-collapse: collapse;
}
th {
cursor: pointer;
}
td.detailsColumn {
-webkit-padding-start: 2em;
text-align: end;
white-space: nowrap;
}
a.icon {
-webkit-padding-start: 1.5em;
text-decoration: none;
user-select: auto;
}
a.icon:hover {
text-decoration: underline;
}
a.file {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;
}
a.dir {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;
}
a.up {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
}
html[dir=rtl] a {
background-position-x: right;
}
#parentDirLinkBox {
margin-bottom: 10px;
padding-bottom: 10px;
}
#listingParsingErrorBox {
border: 1px solid black;
background: #fae691;
padding: 10px;
display: none;
}
</style>
<title id="title">/home/liukairui/CODE/ 的索引</title>
</head>
<body>
<div id="listingParsingErrorBox">糟糕!Google Chrome无法解读服务器所发送的数据。请<a
href="http://code.google.com/p/chromium/issues/entry">报告错误</a>,并附上<a href="LOCATION">原始列表</a>。</div>
<h1 id="header">/home/liukairui/CODE/ 的索引</h1>
<div id="parentDirLinkBox" style="display: block;">
<a id="parentDirLink" class="icon up" href="/home/liukairui/CODE/..">
<span id="parentDirText">[上级目录]</span>
</a>
</div>
<table>
<thead>
<tr class="header" id="theader">
<th id="nameColumnHeader" tabindex="0" role="button">名称</th>
<th id="sizeColumnHeader" class="detailsColumn" tabindex="0" role="button">
大小
</th>
<th id="dateColumnHeader" class="detailsColumn" tabindex="0" role="button">
修改日期
</th>
</tr>
</thead>
<tbody id="tbody">
{
{HERETOREPLACE}}
</tbody>
</table>
</body>
</html>
var fs=require("fs");
var http=require("http");
var server=http.createServer();
server.on("request",function(req,res){
var content="";
res.setHeader("Content-Type","text/html;charset=utf-8")
fs.readdir("./",function(error,files){
if(error){
res.end("404 Not Find");
return;
}else{
files.forEach(function(FILENAME){
content+=`<tr><td data-value="${
FILENAME}/"><a class="icon dir" href="/home/liukairui/CODE/${
FILENAME}/">${
FILENAME}/</a></td><td class="detailsColumn" data-value="0"></td><td class="detailsColumn" data-value="1602264292">2020/10/10 上午1:24:52</td></tr>`
})
}
});
fs.readFile("./index.html",function(error,file){
if(error)
res.end("404 Not Find");
else{
// 暴力使用字符串替换实现
res.
这篇博客详细介绍了Node.js的起步,包括创建简单程序、HTTP服务、响应内容类型、模块化、实现Apache功能和留言版功能。重点讲解了Node.js中的JavaScript、响应Content-Type、Express框架的使用,以及如何处理文件和目录。此外,还涉及到了npm管理和文件操作路径。博客提供了丰富的示例代码,帮助读者深入理解Node.js开发。
最低0.47元/天 解锁文章

2245

被折叠的 条评论
为什么被折叠?



