要点
- const exports = [ module.exports = {} ] 原理
// add 移动到一个单独的文件
// 导入
// ./ /
// 补齐
// .js || .json || .node
const add = require('./add');
console.log(add(1, 1));
console.log(add)
// 如果不是文件的话
// 尝试看看是不是文件夹
// 1. package.json 里面的 main 字段
// 2. 找里面的 index.js ||.json || .node
const sub = require('./sub');
console.log(sub)
// 如果不是 ./ / 开头的话
// 加载内置模块 第三方模块
const http = require('http');
console.log(http)
// 文件夹以及文件同名
// 先尝试文件
const add = require('./add');
console.log(add)
// 第三方模块 node_modules中
const atest = require('atest');
console.log(atest)
const lodash = require('lodash');
console.log(lodash)
简介
Node.js 就是js,基于Chrome v8 引擎运行在服务端 可以直接操作操作系统
安装(windows 要配置环境变量,重启cmd / vscode)
- 官网
- brew
特点
- 单线程
- 非阻塞 I/O
- 访问文件
- 网络请求
- 数据库查询
- 键盘/鼠标交互
- 事件驱动
用途
- 工具
- 构建工具 webpack
- 编译工具 babel
- 脚手架 vue-cli
- 后端服务
客户端和服务端
- 一个js放在浏览器执行,就是普通的js,放在服务端node环境执行,就是node.js
- node.js可以搭建服务器
- 哪个电脑搭建服务器就是服务端,哪个电脑去访问就是客户端(相对)
const http = require('http')
const server = http.createServer((req, res) => {
res.write('111')
res.end()
})
server.listen(3000)
每次修改需要重新启动
node http.js
nodemon 热更新,不用手动重启
npm install nodemon -g
nodemon http.js
node中的模块化
- node 遵循common.js规范
- commandjs 早于 esm
- 针对客户端:AMD sea.js CMD require.js
- node: 装好后天生的common.js规范,每个文件都是一个独立的模块,变量不会相互污染
- 模块加载的优先级, 先文件再目录
以文件的形式(以文件模式引入: ./ 不能省略)
Ma.js
console.log("我是Ma.js文件");
require("./Mb");
let a = 10;
class Person{
constructor(){
this.name = "张三";
}
hobby(){
console.log("喜欢篮球");
}
}
// 第一种导出方式
// module.exports = {
// a,
// Person
// }
//第二种导出方式
exports.a = a;
exports.Person = Person;
// exports = add;
// 相当于::
// module.exports = {
// add: add
// }
// exports 是 module.exports 的引用;
// const exports = [ module.exports = {} ]
// export = { } 无法改变module.exports的值,通过 . 可以
// exports = add; 使得上述联系断开
Mb.js
console.log("我是模块b");
index.js
// 以文件模式引入: ./ 不能省略, .js后缀可省略
let Ma = require("./Ma");
console.log(Ma.a)
let cai = new Ma.Person();
cai.hobby();
以目录的形式(以文件模式引入: ./ 不能省略)
a.js
console.log("我是a.js")
require("test");
b.js
console.log("我是b.js")
index.js
console.log("我是index.js");
require("./a");
require("./b");
在home目录外的index.js中引入,并运行这个index.js
自动会去查找home 目录中的index.js
require("./home");
node_modules里的模块(引入时不需要加./ ,加了会报错)
package.json
描述、功能性的文件,既有描述,也有功能
下次找mytest 模块,先读package.json, 读到main 去找主入口
{
"name": "mytest",
"version": "1.0",
"main": "main.js" //主入口,不写默认index.js
}
a.js
console.log('a.js')
b.js
console.log('b.js')
index.js
require('./a')
require('./b')
module.exports = {
a: 10,
b() {
console.log('o my gad')
}
}
main.js
console.log('main.js')
// ***********************************************
// 其他地方引入时:
// node_modules里的模块;
// 不需要加 ./, 自动找index.js
// 主入口为 index.js
// let {a,b} = require("mytest");
// console.log(a, b);
// b();
// 主入口改成main.js
require("mytest")
- 主入口为 index.js
- 主入口改成main.js
npm 包管理器
- node_modules 中放第三方模块
- npm 包管理器 www.npmjs.com
- npm install jauery 可以安装前/后端的依赖和模块
- npm uninstall 删除
- 内置模块不需要安装,外置模块需要安装
node 中的内置模块:
Buffer,C/C++Addons,Child Processes,
Cluster,Console,Crypto,Debugger,
DNS,Domain,Errors,Events,
File System,
Globals,HTTP,HTTPS,Modules,Net,OS,
Path,Process,P unycode,Query Strings,
Readline,REPL,Stream,
String De coder,Timers,TLS/SSL,
TTY,UDP/Datagram,URL, Utilities,V8,VM,ZLIB;
- npm init 创建package.json
{
"name": "code",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"jquery": "^3.4.1"
},
"devDependencies": {
"axios": "^0.19.0"
},
// 命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}
依赖
dependencies:运行依赖,上线后也需要用 jquery、vue、react;
devDependencies:开发依赖,开发时作为开发工具用一下 sass less;
写在这里 npm install 时会自动查找,装到node_modules
node_modules 在本层找,没有则向上找,直到系统根目录 npm root -g
^ 最低兼容版本
- npm install axios --save
- npm i axios --save-dev
npm install
工具类的,很多项目都需要用,装到全局。仅与本项目有关系的,装到本项目下:
npm i gulp 装在当前目录下的node_modeules
npm i gulp -g 装在系统根目录 npm root -g 得到全局的node_modeules下
其他
npm updata 更新
npm i jauery@3.4.1 安装指定版本
fs模块
文件操作
异步写法
文件写入
const fs = require("fs"); //文件操作
// 增删改查;
// 1.文件操作 2.目录操作;
// 文件操作
fs.writeFile("1.txt","我是写入的文字11111",function(err){
if(err){
return console.log(err);
}
console.log("写入成功");
})
const fs = require("fs"); //文件操作
// a:追加写入;w 写入(默认);r:读取(写入这里不行)
fs.writeFile("1.txt","我是追加的文字",{flag:"a"},function(err){
if(err){
return console.log(err);
}
console.log("写入成功");
})
文件读取
const fs = require("fs"); //文件操作
// 文件读取
fs.readFile("1.txt","utf8",(err,data)=>{
if(err){
return console.log(err);
}
console.log(data);
})
const fs = require("fs"); //文件
fs.readFile("1.txt",(err,data)=>{
if(err){
return console.log(err);
}
console.log(data)
console.log(data.toString());
})
同步
// 所有文件操作 没有加Sync都是异步 否则是同步;
let data = fs.readFileSync("1.txt");
console.log(data.toString());
修改
// 修改;(修改名称);
fs.rename("1.txt","2.txt",err=>{
if(err){
return console.log(err);
}
console.log("修改成功");
});
删除
// 删除;
fs.unlink("2.txt",(err)=>{
if(err){
return console.log(err);
}
console.log("删除成功");
})
复制
// 复制; 先读取 在写入 的过程;
// 提供的复制方法
fs.copyFile("index.html","index2.html",err=>{
if(err){
return console.log(err);
}
console.log("复制成功!");
})
// 自己写的复制
function mycopy(src,dest){
fs.writeFileSync(dest,fs.readFileSync(src));
}
mycopy("index.html","test2.html");
目录操作
// 创建目录
fs.mkdir("11",err=>{
if(err){
return console.log(err);
}
console.log("创建成功");
})
// 修改目录名称
fs.rename("11", "22", err => {
if (err) {
return console.log(err);
}
console.log("修改成功");
})
// 读取目录;(第一个参数是路径)
fs.readdir("22",(err,data)=>{
if(err){
return console.log(err);
}
console.log(data);
})
// 删除目录(必须是空文件夹/目录)
// 第一个参数是路径
fs.rmdir("22/44",err=>{
if(err){
return console.log(err);
}
console.log("删除成功");
})
// 判断文件或者目录是否存在
fs.exists("index.html",exists=>{
console.log(exists); // true/false
})
// 获取文件或者目录的详细信息;
fs.stat("index.html",(err,stat)=>{
if(err){
return console.log(err);
}
console.log(stat);
// 判断文件是否是文件
// let res = stat.isFile();
// 是否是一个文件夹;
let res = stat.isDirectory();
console.log(res);
})
// 删除非空文件夹;
// 不进回收站,删除前不备份就没了
// 先把目录里的文件删除-->删除空目录;
// 22
function removeDir(path){
let data = fs.readdirSync(path);
// ["33","1.txt","2.html"];
for(let i=0;i<data.length;i++){
// 是文件或者是目录; --->?文件 直接删除?目录继续查找;
let url = path + "/" + data[i];
let stat = fs.statSync(url);
if(stat.isDirectory()){
//目录 继续查找;
removeDir(url);
}else{
// 文件 删除
fs.unlinkSync(url);
}
}
// 删除空目录
fs.rmdirSync(path);
}
removeDir("22");
buffer 类
buffer 创建
// buffer 创建
// buffer 类 数据格式 不是node中的模块
// new Buffer()
// 16进制呈现,在计算机中是二进制
let buffer = Buffer.alloc(10);
console.log(buffer);
let buffer = Buffer.from("大家好");
console.log(buffer);
let buffer = Buffer.from([0xe5,0xa4,0xa7,0xe5,0xae,0xb6,0xe5,0xa5,0xbd]);
console.log(buffer);
console.log(buffer.toString());
乱码问题
// 乱码问题
let buffer1 = Buffer.from([0xe5,0xa4,0xa7,0xe5]);
let buffer2 = Buffer.from([0xae,0xb6,0xe5,0xa5,0xbd]);
console.log(buffer1.toString());
console.log(buffer2.toString());
let newbuffer = Buffer.concat([buffer1,buffer2]);
console.log(newbuffer.toString());
let buffer1 = Buffer.from([0xe5,0xa4,0xa7,0xe5]);
let buffer2 = Buffer.from([0xae,0xb6,0xe5,0xa5,0xbd]);
let { StringDecoder } = require("string_decoder");
let decoder = new StringDecoder();
let res1 = decoder.write(buffer1);
let res2 = decoder.write(buffer2);
console.log(res1);
console.log(res2);
console.log(res1+res2);
steam 流
- 数据/文件切割成小块,依次传递,时间变长,性能变高
const fs = require("fs");
let res = fs.readFileSync("1.txt");
console.log(res)
console.log(res.toString());
const fs = require("fs");
let rs = fs.createReadStream("1.txt");
let ws = fs.createWriteStream("2.txt");
rs.on("data",chunk=>{
console.log(chunk); // chunk 小方块
})
// 流会把数据分成64kb的小文件传输;
// 创建一个65kb的文件;
let buffer = Buffer.alloc(64*1024);
fs.writeFile("64kb",buffer,err=>{
if(err){
return console.log(err);
}
console.log("写入成功");
})
const fs = require("fs");
let rs = fs.createReadStream("65kb");
let num = 0;
rs.on("data",chunk=>{
num++;
console.log(chunk); // chunk 小方块
console.log(num);
})
const fs = require("fs");
let rs = fs.createReadStream("64kb");
let num = 0;
rs.on("data",chunk=>{
num++;
console.log(chunk); // chunk 小方块
console.log(num);
})
const fs = require("fs");
let rs = fs.createReadStream("1.txt");
let num = 0;
let str = "";
rs.on("data",chunk=>{
num++;
str += chunk;
// console.log(chunk); // chunk 小方块
console.log(num);
})
// 流完成了;
rs.on("end",()=>{
console.log(str);
})
const fs = require("fs");
let rs = fs.createReadStream("1.txt");
let ws = fs.createWriteStream("2.txt");
rs.pipe(ws);
模版引擎
模板引擎:模板引擎是web应用中动态生成html的工具,负责将数据和模板结合;
常见模板引擎有:ejs、jade(现更名为pug)、Handlebars、Nunjucks、Swig等;
使用模板引擎可以是项目结构更加清晰,结构更加合理,让项目维护变得更简单;
-
什么是模板引擎
-
pug/nunjucks模板引擎
-
表达式
-
判断语句
-
循环语句
-
宏模式
-
导入导出
pug模板引擎使用
-
安装pug
npm i pug -g -
pug常用语法
- pug语法:通过缩进关系,代替以往html的层级包含关系,如 个简单的静态 可以表达为,注意要统一使用tab或者空格缩进,不要混用
- 内联书写层级,a: img
- style属性:div(style={width:”200px”,color:”red”})
- 使用”-”来定义变量,使用“=”把变量输出到元素内;
- 通过 #{variable} 插 相应的变量值
- html 元素属性通过在标签右边通过括号包含(可以通过判断来添加)
- 文本通过在 字前 添加竖线符号“|”可让 jade 原样输出内容 在html标签标记后 通过空格隔开 本内容 在html标签标记后通过添加引号“.”添加块级文本
- 注释:可以通过双斜杠进 注释,jade有3种注释 式,可以分别对应输出html 注释、 输出html注释、块级html注释
- 循环:each val in [1,2,3]
- 判断语句:”if else” case when default
- mixin:混合模式
- include common/footer.pug 通过include引入外部文件
-
练习工具 hade;
npm i hade -g
nunjucks模板引擎在koa中的应用
-
安装koa-nunjucks-2
-
使用nunjucks
const nunjucks = require('koa-nunjucks-2'); app.use(nunjucks({ ext:"html", //指定模板后缀 path:path.join(__dirname,'views'), //指定视图目录 nunjucksConfig:{ trimBlocks:true //开启转义,防止xss漏洞 } })) -
推荐使用”.njk“后缀名
-
nunjucks的语法使用
-
变量:
{{username}} -
注释:
{# Loop through all the users #} -
if
{% if hungry %} I am hungry {% elif tired %} I am tired {% else %} I am good! {% endif %} -
for
<h1>Posts</h1> <ul> {% for item in items %} <li>{{ item.title }}</li> {% else %} <li>This would display if the 'item' collection were empty</li> {% endfor %} </ul> -
过滤器
{{ foo | replace("foo", "bar") | capitalize }} -
模板继承block/extends
-
定义父类模板
<h1>我是公共模板</h1> <div class="leftContent"> {% block left %} 这边是左侧的内容 {% endblock %} {% block right %} 这边是右侧的内容 {% endblock %} {% block somevalue %} 我是一些数据 {% endblock %} </div> -
继承父类模板
{% extends "common.html" %} {% block left %} 我是左侧的内容1111 {% endblock %} {% block right %} 我是右侧的内容11111 {% endblock %} {% block somevalue %} {{ super() }} {% endblock %}
-
-
Macro(宏标签)可以定义可复用的内容,类似与编程语言中的函数
- 定义
{% macro pet(animalName,name="小白") %} <div> 这里是一只{{animalName}};他的名字是{{name}} </div> {% endmacro %}-
调用
{{pet("狗狗")}}
-
include/import
-
include 引入文件
{% include "footer.html" %} -
import 导入文件
- 定义
{% macro pet(animalName) %} <p>这是一只{{animalName}}</p> {% endmacro %} {% macro book(bookName) %} <p>这是一本书,名字叫{{bookName}}</p> {% endmacro %}-
调用
{% import 'somemodule.html' as fn %} {{fn.pet("狗狗")}} {{fn.book("nodejs从入门到实践")}}
-
-