环境安装
Node.js运行环境安装
npm网址:https://www.npmjs.com/
第三方模块nrm(切换npm安装源)
nrm can help you easy and fast switch between different npm registries, now include: npm, cnpm, taobao, nj(nodejitsu).
安装:
npm install nrm –g
使用:
$ nrm ls
* npm ----- https://registry.npmjs.org/
yarn ----- https://registry.yarnpkg.com
cnpm ---- http://r.cnpmjs.org/
taobao -- https://registry.npm.taobao.org/
nj ------ https://registry.nodejitsu.com/
skimdb -- https://skimdb.npmjs.com/registry
-----------------------------------------------------------------------------------
$ nrm use cnpm //switch registry to cnpm
Registry has been set to: http://r.cnpmjs.org/
nrm ls报错,信息如下
internal/validators.js:124
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
解决方案找到npm的全局安装目录下的 npm\node_modules\nrm\cli.js
cli.js中第17行 const NRMRC = path.join(process.env.HOME, '.nrmrc');
改为:const NRMRC = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], '.nrmrc');
第三方模块 nodemon()
nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.
安装:npm install nodemon –g
使用:在命令行工具中用nodemon命令替代node命令执行文件
常用模块
文件模块
文件读取
const fs = require('fs')
//普通文件
fs.readFile('./test.txt', (err, data)=> {
// <Buffer 68 65 6c 6c 6f 20 6e 6f 64 65 6a 73 0d 0a>
// 所以我们可以通过 toString 方法把其转为我们能认识的字符
// console.log(data)
// console.log(error)
// console.log(data)
// 在这里就可以通过判断 error 来确认是否有错误发生
if (err) {
console.log('读取文件失败了')
} else {
console.log(data.toString())
}
})
/*
If no encoding is specified, then the raw buffer is returned.
If options is a string, then it specifies the encoding:
fs.readFile('/etc/passwd', 'utf8', callback);
*/
//图片读取
fs.readFile('./test.jpg', (err, data)=> {
if (err) {
console.log('读取文件失败了')
} else {
// data 默认是二进制数据,可以通过 .toString 转为咱们能识别的字符串
// 图片就不需要指定编码了,因为我们常说的编码一般指的是:字符编码
console.log(data)
}
})
文件写入
const fs = require('fs')
/*
fs.writeFile(file, data[, options], callback)#
file <string> | <Buffer> | <URL> | <integer> filename or file descriptor
data <string> | <Buffer> | <TypedArray> | <DataView> | <Object>
options <Object> | <string>
encoding <string> | <null> Default: 'utf8'
mode <integer> Default: 0o666
flag <string> See support of file system flags. Default: 'w'.
callback <Function>
err <Error>
*/
fs.writeFile('./hello.md', '大家好,给大家介绍一下,我是Node.js', err=>{
// console.log('文件写入成功')
// console.log(err)
if (err) {
console.log('写入失败')
} else {
console.log('写入成功了')
}
})
获取目录下的文件名
const fs = require('fs');
fs.readdir('./dir',(err,files)=>{
if (err){
return console.log("目录不存在");
}
console.log(files);
})
查询文件信息
//fs.stat(path, callback)
const fs = require('fs')
fs.stat('./package.json', (err, stats) => {
console.log(stats.isDirectory());
console.log(stats);
})
| 方法 | 描述 |
|---|---|
| stats.isFile() | 如果是标准文件,返回true |
| stats. isDirectory() | 如果是路径,返回true |
| stats. isBlockDevice() | 如果是块设备,返回true |
| stats. isCharacterDevice() | 如果是字符设备,返回true |
| stats. isSymbolicLink() | 如果是符号连接,返回true |
| stats.isFIFO() | 如果是FIFO,返回true |
| stats. isSocket() | 如果是UNIX套接字,返回true |
http模块
// 导入http模块
const http = require('http');
//创建网站服务器
const app = http.createServer();
//监听客服端访问服务端的事件
app.on('request',(req,res)=>{
res.end('ok');
})
//监听端口
app.listen(3000,()=>{
console.log("服务器启动成功,可以通过http://127.0.0.1:3000/")
});
监听request事件
app.on('request',(req,res)=>{})
request 请求事件处理函数,需要接收两个参数:
req 请求对象
请求对象可以用来获取客户端的一些请求信息,例如请求路径
res 响应对象
响应对象可以用来给客户端发送响应消息
req 请求对象
-
获取请求路径:
req.url
获取到的是端口号之后的那一部分路径,也就是说所有的 url 都是以 / 开头的.
-
获取请求我的客户端的地址是:
req.socket.remoteAddress,
req.socket.remotePort
-
获取请求方式
req.method
常用方法:
方法 描述 GET 请求指定的页面信息,并返回实体主体 POST 向指定资源提交数据进行处理请求,数据被包含在请求体中。 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 PUT 从客户端向服务器传送的数据取代指定的文档的内容 DELETE 请求服务器删除指定的页面 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 OPTIONS 允许客户端查看服务器的性能 TRACE 回显服务器收到的请求,主要用于测试或诊断 PATCH 实体中包含一个表,表中说明与该URI所表示的原内容的区别 MOVE 请求服务器将指定的页面移至另一个网络地址 COPY 请求服务器将指定的页面拷贝至另一个网络地址 LIN 请求服务器建立链接关系 UNLINK 断开链接关系 WRAPPED 允许客户端发送经过封装的请求 Extension-mothed 在不改动协议的前提下,可增加另外的方法 -
获取请求报文
req.headers
-
GET请求参数
-
参数被放置在浏览器地址栏中,例如:http://localhost:3000/?name=aa&age=20
-
参数获取需要借助系统模块url,url模块用来处理url地址
const http = require('http'); // 导入url系统模块 用于处理url地址 const url = require('url'); const app = http.createServer(); app.on('request', (req, res) => { // 将url路径的各个部分解析出来并返回对象 // true 代表将参数解析为对象格式 let {query} = url.parse(req.url, true); console.log(query); }); app.listen(3000); -
-
POST请求参数
-
参数被放置在请求体中进行传输
-
获取POST参数需要使用data事件和end事件
-
使用querystring系统模块将参数转换为对象格式
const http = require('http'); // 导入系统模块querystring 用于将HTTP参数转换为对象格式 const querystring = require('querystring'); const app = http.createServer(); app.on('request', (req, res) => { let postData = ''; // 监听参数传输事件 req.on('data', (chunk) => postData += chunk;); // 监听参数传输完毕事件 req.on('end', () => { console.log(querystring.parse(postData)); }); }); app.listen(3000); -
res 响应对象
-
res.write 可以用来给客户端发送响应数据
//write 可以使用多次,但是最后一定要使用 end 来结束响应,否则客户端会一直等待 res.write('hello') res.write(' nodejs') // 告诉客户端,我的话说完了,你可以呈递给用户了 res.end() -
res.end
// 上面的方式比较麻烦,推荐使用更简单的方式,直接 end 的同时发送响应数据,响应内容只能是二进制数据或者字符串 res.end('hello nodejs') -
res.setHeader
// 服务端默认发送的数据,是 utf8 编码的内容,浏览器在不知道服务器响应内容的编码的情况下会按照当前操作系统的默认编码去解析,解决方法是告知浏览器发送的内容是什么编码的 //在 http 协议中,Content-Type 就是用来告知浏览器发送的数据内容是什么类型 // text/plain 就是普通文本 res.setHeader('Content-Type', 'text/plain; charset=utf-8') //如果你发送的是 html 格式的字符串,则也要告诉浏览器我给你发送是 text/html 格式的内容 res.setHeader('Content-Type', 'text/html; charset=utf-8') // 图片就不需要指定编码了,因为我们常说的编码一般指的是:字符编码 res.setHeader('Content-Type', 'image/jpeg') -
res.statusCode
//设置状态码 //状态码 302 临时重定向 // 实现功能,临时重定向,让用户重新请求 / 首页 res.statusCode = 302 res.setHeader('Location', '/') res.end()
url模块
- const parseObj = url.parse(req.url, true)
使用 url.parse 方法将路径解析为一个方便操作的对象,第二个参数为 true 表示直接将查询字符串转为一个对象(通过 query 属性来访问)
//要解析的url地址
//将查询参数解析成对象形式
let { query, pathname } = url.parse(req.url, true);
path模块
// 用来操作路径的
const path = require('path')
// 获取一个路径中的扩展名部分
// extname extension name
console.log(path.extname('c:/a/b/c/d/hello.txt'))
// 拼接路径
// 拼出public/uploads/avatar
const finalPath = path.join('public', 'uploads','avatar');
// __dirname 文件当前目录
// 拼出helloworld.js文件路径
const helloworldPath = path.join(__dirname, 'helloworld.js')
router模块(功能:实现路由)
使用步骤:
-
获取路由对象
-
调用路由对象提供的方法创建路由
-
启用路由,使路由生效
const getRouter = require('router');
const router = getRouter();
router.get('/index', (req, res) => {
res.end('Hello World!');
})
server.on('request', (req, res) => {
// 启用路由功能
router(req, res, () => {});
})
serve-static(功能:实现静态资源访问服务)
步骤:
-
引入serve-static模块获取创建静态资源服务功能的方法
-
调用方法创建静态资源服务并指定静态资源服务目录
-
启用静态资源服务功能
const path = require('path');
const serveStatic = require('serve-static');
const serve = serveStatic(path.join(__dirname, 'public'));
server.on('request', () => {
// 启用静态资源访问服务功能
serve(req, res, () => {});
})
server.listen(3000)
art-template模板引擎
-
安装:npm i -S art-template
-
模板配置:
向模板中导入变量 template.defaults.imports.变量名 = 变量值;
设置模板根目录 template.defaults.root = 模板目录;
设置模板默认后缀 template.defaults.extname = '.art';
模板引擎的本质就是字符串的拼接
初步使用:
// 导入模板引擎模块
const template = require('art-template');
// 将特定模板与特定数据进行拼接
const html = template('./views/index.art',{
data: {
name: 'aaa',
age: 20
}
});
-----------------------------------------------------------------
<div>
<span>{{data.name}}</span>
<span>{{data.age}}</span>
</div>
模板引擎语法:
-
art-template同时支持两种模板语法:标准语法和原始语法。
-
标准语法可以让模板更容易读写,原始语法具有强大的逻辑处理能力。
-
输出
-
标准语法:{{ 数据 }}
-
原始语法:<%=数据 %>
const template = require('art-template'); const path = require('path'); const views = path.join(__dirname, 'views', 'test.art'); const html = template(views, { name: 'aaa', age: 20, content: '<h1>我是标题</h1>' }) console.log(html);<!-- test.art --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!-- 标准语法 --> <p>{{ name }}</p> <p>{{ 1 + 1 }}</p> <p>{{ 1 + 1 == 2 ? '相等' : '不相等' }}</p> <p>{{ content }}</p> <p>{{@ content }}</p> <!-- 原始语法 --> <p><%= name %></p> <p><%= 1 + 2%></p> <p><%= 1 + 1 == 2 ? '相等' : '不相等' %></p> <p><%= content%></p> <p><%- content%></p> </body> </html>如果数据中携带HTML标签,默认模板引擎不会解析标签。
-
-
条件判断
<!-- 标准语法 --> {{if 条件}} ... {{/if}} {{if v1}} ... {{else if v2}} ... {{/if}} <!-- 原始语法 --> <% if (value) { %> ... <% } %> <% if (v1) { %> ... <% } else if (v2) { %> ... <% } %>参考
{{if age > 18}} 年龄大于18 {{else if age < 15 }} 年龄小于15 {{else}} 年龄不符合要求 {{/if}} <% if (age > 18) { %> 年龄大于18 <% } else if (age < 15) { %> 年龄小于15 <% } else { %> 年龄不符合要求 <% } %>**循环** -
循环
标准语法:{{each 数据}} {{/each}} 原始语法:<% for() { %> <% } %>参考
<ul> {{each users}} <li> {{$value.name}} {{$value.age}} {{$value.sex}} </li> {{/each}} </ul> <ul> <% for (var i = 0; i < users.length; i++) { %> <li> <%=users[i].name %> <%=users[i].age %> <%=users[i].sex %> </li> <% } %> </ul> -
子模版
使用子模板可以将网站公共区块(头部、底部)抽离到单独的文件中。
标准语法:{{include '模板'}} 原始语法:<%include('模板') %><!-- 标准语法 --> {{include './header.art'}} <!-- 原始语法 --> <% include('./header.art') %> -
模板继承
使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件。
参考
<!doctype html> <html> <head> <meta charset="utf-8"> <title>HTML骨架模板</title> {{block 'head'}}{{/block}} </head> <body> {{block 'content'}}{{/block}} </body> </html><!--index.art 首页模板--> {{extend './layout.art'}} {{block 'head'}} <link rel="stylesheet" href="custom.css"> {{/block}} {{block 'content'}} <p>This is just an awesome page.</p> {{/block}} -
设置模板根目录 template.defaults.root = 模板目录;
使用
// 引入模板引擎 const template = require('art-template'); // 配置模板的根目录 template.defaults.root = path.join(__dirname, 'views'); //到views下找index.art const html = template('index.art', {}); console.log(html);
常用方法
1. toString()
转为字符串
data.toString()
综合应用
1. 实现静态简易服务器
const http = require("http");
const fs = require('fs');
const path = require('path');
// 设置静态文件目录
const staticDir = path.join(__dirname, 'static')
// 创建网站服务器
const app = http.createServer();
// 监听request事件
app.on('request',(req,res)=>{
let url = req.url;
let filepath = '/index.html';
if (url !== '/'){
filepath = url;
}
fs.readFile(path.join(staticDir,filepath),(err,data)=>{
if (err){
return res.end("404 Not Found.");
}
res.end(data);
})
})
//监听端口
app.listen(3000,()=>{
console.log("服务器启动成功,可以通过http://127.0.0.1:3000/")
});
浙公网安备 33010602011771号