课程链接
是什么
可以让js脱离浏览器环境运行的基于谷歌V8的引擎
优势:
运行node
- 可以直接在终端使用node进行简单的编程
- 创建js文件,在终端输入
node 文件名
即可运行文件,结果将输出在终端
模块与线程
引入模块
使用require API
const fs = require("fs");
使用fs模块读写文件
使用同步方法:
const fs = require("fs");
const textIn = fs.readFileSync("./txt/input.txt", "utf-8");
console.log(textIn);
const textOut = `This is what we know: ${textIn}. \nCreated on ${Date.now()}`;
fs.writeFileSync("./txt/output.txt", textOut);
console.log("File Written");
线程
同步与异步:
使高负荷的工作在后台运行,不阻塞前台工作
使用异步让IO等耗时的工作在后台运行,前台单线程中多个用户可以轮流进行小工作量的操作,当后台工作完成,回调函数会将数据返回前台
const fs = require("fs");
//同步方法
// const textIn = fs.readFileSync("./txt/input.txt", "utf-8");
// console.log(textIn);
// const textOut = `This is what we know: ${textIn}. \n Created on ${Date.now()}`;
// fs.writeFileSync("./txt/output.txt", textOut);
// console.log("File Written");
//非阻塞方法,回调地狱
fs.readFile("./txt/start11.txt", "utf-8", (err, data1) => {
if (err) console.log("ERROR:", err);
fs.readFile(`./txt/${data1}.txt`, "utf-8", (err, data2) => {
console.log(data2);
fs.readFile("./txt/append.txt", "utf-8", (err, data3) => {
console.log(data3);
//只需要读,第四个参数无data
fs.writeFile("./txt/final.txt", `${data2}\n${data3}`, "utf-8", (err) => {
console.log("Finally finished!");
});
});
});
});
console.log("Read done!"); //由于异步,先出现
使用http创建server
引入:
const http = require("http");
运行:
//Server
//req获取到所有request信息
const server = http.createServer((req, res) => {
console.log(req);
res.end("hello from the server");
});
//端口号,主机,回调函数
server.listen(8000, "127.0.0.1", () => {
console.log("Listening to requests on port 8000");
});
此时可以访问主机:端口
url模块
const url = require("url");
req.url可以获取到请求的url
使用parse解析获取到的数据
- 当传入一个url网址,如
https://www.bilibili.com/video/BV1wx4y157nD/?vd_source=6a1c5779cb112891ea6b1efc0c86673c
- 使用 url.parse(req.url,true);
- true 为将获得的结果放入一个对象中
解析数据并储存:
const { query, pathname } = url.parse(req.url, true);
const server = http.createServer((req, res) => {
// console.log(req);
console.log(req.url);
const pathName = req.url;
if (pathName === "/") {
res.end("hello from the server");
} else {
res.writeHeader(404, {
"Content-type": "text/html",
//自定义头
"my-own-header": "hello-world",
});
//写入文件
res.end("<h1>Page Not Found</h1>");
}
});
定义简单的api
__dirname
是当前文件所在位置路径,避免相对路径出问题
const Data = fs.readFileSync(`${__dirname}/dev-data/data.json`, "utf-8");
const dataObj = JSON.parse(Data);
//在creatServer函数中
if (pathName === "/" || pathName === "overview") {
res.end("hello from the server");
} else if (pathName === "/api") {
//定义响应的对象类型
res.writeHead(200, { "Content-type": "application/json" });
res.end(Data);
} else {
//定义响应头
res.writeHeader(404, {
"Content-type": "text/html",
"my-own-header": "hello-world",
});
res.end("<h1>Page Not Found</h1>");
}
html模板实例:
首先使用占位符为替换做准备
模板可以使用任何占位符,这里使用 {% PLACEHOLDER %}
<body>
<div class="container">
<h1>🌽 Node Farm 🥦</h1>
<figure class="product">
<div class="product__organic {%NOT_ORGANIC%}"><h5>Organic</h5></div>
<a href="/overview" class="product__back">
<span class="emoji-left">👈</span>Back
</a>
<div class="product__hero">
<span class="product__emoji product__emoji--1">{%IMAGE%}</span>
</div>
<a href="#" class="product__link">
<span class="emoji-left">🛒</span>
<span>Add to shopping card ({%PRICE%}€)</span>
</a>
<p class="product__description">
{%DESCRIPTION%}
</p>
</figure>
</div>
</body>
</html>
替换模板占位符
const replaceTemplate = (temp, product) => {
let output = temp.replace(/{%PRODUCTNAME%}/g, product.productName);
output = output.replace(/{%IMAGE%}/g, product.image);
output = output.replace(/{%PRICE%}/g, product.price);
output = output.replace(/{%FROM%}/g, product.from);
output = output.replace(/{%NUTRIENTS%}/g, product.nutrients);
output = output.replace(/{%QUANTITY%}/g, product.quantity);
output = output.replace(/{%DESCRIPTION%}/g, product.description);
output = output.replace(/{%ID%}/g, product.id);
if(!product.organic) output = output.replace(/{%NOT_ORGANIC%}/g, 'not-organic');
return output;
}
在server中进行调用即可:
if (pathname === '/' || pathname === '/overview') {
res.writeHead(200, {
'Content-type': 'text/html'
});
//传入一个json data,最终返回一个循环遍历好的数组
//模板网页的占位符被data替换了
//但是我们不需要一个数组,而是需要一个长字符串,即一整个网页代码最终插入到server中,因此使用join
const cardsHtml = dataObj.map(el => replaceTemplate(tempCard, el)).join('');
const output = tempOverview.replace('{%PRODUCT_CARDS%}', cardsHtml);
//最终输出到网页中
res.end(output);
模块
将上面的函数放到另一个文件,并导出:
module.exports = (temp, product) => {
let output = temp.replace(/{%PRODUCTNAME%}/g, product.productName);
output = output.replace(/{%IMAGE%}/g, product.image);
output = output.replace(/{%PRICE%}/g, product.price);
output = output.replace(/{%FROM%}/g, product.from);
output = output.replace(/{%NUTRIENTS%}/g, product.nutrients);
output = output.replace(/{%QUANTITY%}/g, product.quantity);
output = output.replace(/{%DESCRIPTION%}/g, product.description);
output = output.replace(/{%ID%}/g, product.id);
if(!product.organic) output = output.replace(/{%NOT_ORGANIC%}/g, 'not-organic');
return output;
}
此时可以在原文件中导入:
此时 ./
永远为当前文件夹
const replaceTemplate = require('./modules/replaceTemplate');
slugify & nodemon
nodemon可以全局安装,是一个热加载server的插件
在package.json中引入脚本:
此时需要在开发环境中安装nodemon:npm i nodemon --save-dev
{
"name": "starter",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"slugify": "^1.6.5"
},
"devDependencies": {
"nodemon": "^2.0.20"
}
}
slugify可以将地址 信息转换为一个符合网址要求的字符串
指定版本安装:
npm i slugify@1.0.0
检查是否过时:
npm outdated
只接受补丁版本或更低版,将^换为~
“slugify”: “~1.3.4”