js 风格指南
https://github.com/lin-123/javascript
知识点同步
es6 中新增的内容
-
模板字符串
const str = `我是一个字符串`; const strName = "小强"; const sreResult = str + strName; const strResult2 = `${str},${strName}`;
-
replace
替换一个
-
replaceAll
替换所有的
const str1 = "banbana"; console.log(str1.replace("a", "A")); //bAnbana console.log(str1.replace(/a/g, "A")); //bAnbAnA console.log(str1.replaceAll("a", "A")); //bAnbAnA
-
-
const 和 let
const 定义的常量,定义的时候需要设置初始值。定义好之后不能改变
let 用来定义临时变量
const obj = {}; obj.name = "Tom"; //正确 const obj1 = {}; obj1 = { name: "jain" }; //报错 const num = 2; num = 3; //报错
-
箭头函数
箭头函数没有 this,所以不能用来实现继承
箭头函数如果只有一行可以不写 return
const a = (() => 3)(); const b = () => { return 5; }; const c = b();
-
class 类
最主要的就是需要知道可以通过 extends 关键词实现继承
-
解构赋值
const person = {
name: "海绵宝宝",
desc: "住在大菠萝中",
friends: ["派大星", "蟹老板", "小窝"],
};const { name } = person;
console.log(name); //海绵宝宝
console.log(desc); //报错
// const {desc,...rest}=person;
// console.log(desc); //住在大菠萝中
// console.log(rest);//{name: '海绵宝宝', friends:['派大星','蟹老板','小窝']}const {
desc,
friends: [aa],
} = person;
// console.log(friends);//报错
console.log(aa); //派大星const person1 = {
name: "小新",
desc: "住在春日部",
fav: "不喜欢吃青椒",
pet: { name: "小白", desc: "很白" },
};
const {
pet: { name },
} = person1;
console.log(name); //小白 -
扩展运算符
三个点,会生成一个新的对象。常常用在对象的浅拷贝上
const arr = [1, 2, 3]; arr.push(4, 5, 6, 7); console.log(arr); //[1,2,3,4,5,6,7] arr.push([9, 10, 11]); console.log(arr); //[1, 2, 3, 4, 5, 6, 7, Array(3)] arr.push(...[12, 13, 14]); console.log(arr); //[1, 2, 3, 4, 5, 6, 7, Array(3), 12, 13, 14] const bb = [1, 2, 3]; console.log([...bb, ...[5, 6, 7]]); //[1, 2, 3, 5, 6, 7] const obj3 = { id: 1, username: "Tom", age: 18 }; console.log({ ...obj3, username: "Jin" }); //{id: 1, username: 'Jin', age: 18}
数组操作
-
forEach
循环数组,不做任何改变
// item 表示当前项目
// index 表示索引
arr.forEach((item, index) => {});//例:
var arr = [1, 3, 5];
arr.forEach((item) => (item += 1));
console.log(arr); //[1, 3, 5]
var arr = [{ num: 1 }, { num: 2 }, { num: 3 }];
arr.forEach((item) => (item.num += 1));
console.log(arr); //[{num:2},{num:3},{num:4}] 地址不变 -
map
循环数组,生成一个新数组。新数组的每一项是由循环的每一项的返回值生成的,新数组的长度和原数组一致
// item 表示当前项目
// index 表示索引
arr.map((item, index) => {});
//例:
var arr = [1, 2, 3];
var arr1 = arr.map((item) => item * item);
console.log(arr); //[1, 2, 3] 原数组不发生改变
console.log(arr1); //[1, 4, 9]
var arr2 = arr.map((item) => {
item * item;
});
console.log(arr2); //[undefined, undefined, undefined]
var arr3 = arr.map((item) => {
return item * item;
});
console.log(arr3); //[1, 4, 9]
-
reduce
做聚合操作
arr.reduce((pre, item) => {
// pre 上一次的值
// item 当前项目
// 0 初始值
return xx; // 这个返回值作为下一次的上一次的值
}, 0);
//例:
var arr = [1, 2, 3];
var a = arr.reduce((pre, item) => pre + item, 0); //0+1+2+3=6
console.log(a); //6
var b = arr.reduce((pre, item) => pre + item, 10); //10+1+2+3=16
console.log(b); //16var people = [
{ id: 1, name: "卡卡西", zl: 5000 },
{ id: 2, name: "鸣人", zl: 10000 },
{ id: 2, name: "忍者神龟", zl: 30000 },
];
var c = people.reduce((pre, item) => pre + item.zl, 0);
console.log(c); //45000 -
sort
排序
var arr = [1, 2, 3, 6, 8, 9, 56, 45, 23, 91, 26];
//降序
var arr1 = arr.sort((a, b) => b - a);
console.log(arr1); //[91, 56, 45, 26, 23, 9, 8, 6, 3, 2, 1]
//升序
var arr2 = arr.sort((a, b) => a - b);
console.log(arr2); //[1, 2, 3, 6, 8, 9, 23, 26, 45, 56, 91]
//随机排列(随机抽奖)
var arr3 = arr.sort(() => Math.random() - 0.5);
console.log(arr3);
var people = [
{ id: 1, name: "卡卡西", zl: 5000 },
{ id: 2, name: "鸣人", zl: 10000 },
{ id: 3, name: "忍者神龟", zl: 30000 },
];
var people1 = people.sort((a, b) => b.zl - a.zl);
console.log(people1); //[{id:3,name:'忍者神龟',zl:30000},{id:2,name:'鸣人',zl:10000},{id:1,name:'卡卡西',zl:5000}]
- filter
过滤,返回一个数组
var people = [
{ id: 1, name: "卡卡西", zl: 5000 },
{ id: 2, name: "鸣人", zl: 10000 },
{ id: 3, name: "忍者神龟", zl: 30000 },
];
var people1 = people.filter((item) => item.zl > 10000);
console.log(people1); //[{id: 3, name: '忍者神龟', zl: 30000}]
- find
找到符合条件的第一项
- findIndex
找到符合条件的索引。如果不存在返回-1(只取第一个)
- splice
替换,参数一 表示位置,参数二表示个数,后面的参数如果存在那么会进行在指定位置的填充
var bb = [1, 2, 3, 4, 5, 6, 7];
console.log(bb.splice(2, 1)); //[3]
console.log(bb); //[1,2,4,5,6,7]
console.log(bb.splice(2, 1, ["a", "b", "c"])); //[4]
console.log(bb); //[1, 2, Array(3), 5, 6, 7]
console.log(bb.splice(2, 1, ...["a", "b", "c"]));
console.log(bb); //[1, 2, 'a', 'b', 'c', 5, 6, 7]
对象操作
- 深拷贝
逐层拷贝每一级。JSON.stringify 转换为字符串然后 JSON.parse 格式化成对象
var person = {
name: "小新",
desc: "住在春日部的一个幼儿园小朋友",
friends: [
{ id: 1, name: "风间", desc: "小新的跟班" },
{ id: 2, name: "小绿", desc: "小新的幼儿园老师" },
],
};
const person3 = JSON.parse(JSON.stringify(person));
console.log(person);
console.log(person3); //两个person内容一样
//第一级改变
person3.name = "小葵"; //person3的值的修改不会影响到person
console.log(person); //{name: '小新', desc: '住在春日部的一个幼儿园小朋友', friends: Array(2)} Array不变
console.log(person3); //{name: '小葵', desc: '住在春日部的一个幼儿园小朋友', friends: Array(2)} Array不变
//第二级改变
person.friends[1].name = "正南"; //person3的friends属性的第一个数组的name的值的改变,不影响person对应的值
console.log(person); //{name: '小新', desc: '住在春日部的一个幼儿园小朋友', friends: [{ id: 1, name: '风间', desc: '小新的跟班' }, { id:2, name: '正南', desc: '小新的幼儿园老师' }]} Array改变
console.log(person3); //{name: '小葵', desc: '住在春日部的一个幼儿园小朋友', friends: [{ id: 1, name: '风间', desc: '小新的跟班' }, { id:2, name: '小绿', desc: '小新的幼儿园老师' }]} Array不变
- 浅拷贝
只拷贝第一级。可以使用扩展运算符实现
//扩展运算------> ...[内容] ...是扩展运算符;
var person = {
name: "小新",
desc: "住在春日部的一个幼儿园小朋友",
friends: [
{ id: 1, name: "风间", desc: "小新的跟班" },
{ id: 2, name: "小绿", desc: "小新的幼儿园老师" },
],
};
const person2 = { ...person };
console.log(person);
console.log(person2); //person 和 person2 里面的值一样
//第一级改变
person2.name = "小葵"; //person2里的name值改变了,没有影响到person
console.log(person); //{name: '小新', desc: '住在春日部的一个幼儿园小朋友', friends: Array(2)} Array不变
console.log(person2); //{name: '小葵', desc: '住在春日部的一个幼儿园小朋友', friends: Array(2)} Array不变
//第二级改变
person.friends[1].name = "正南";
console.log(person); //{name: '小新', desc: '住在春日部的一个幼儿园小朋友', friends: [{ id: 1, name: '风间', desc: '小新的跟班' }, { id:2, name: '正南', desc: '小新的幼儿园老师' }]} Array改变
console.log(person2); //{name: '小葵', desc: '住在春日部的一个幼儿园小朋友', friends: [{ id: 1, name: '风间', desc: '小新的跟班' }, { id:2, name: '正南', desc: '小新的幼儿园老师' }]} Array改变
-
补充拷贝的特殊情况
/* 完全相等,一个变另一个也变 */
var person = {
name: "小新",
desc: "住在春日部的一个幼儿园小朋友",
friends: [
{ id: 1, name: "风间", desc: "小新的跟班" },
{ id: 2, name: "小绿", desc: "小新的幼儿园老师" },
],
};
const person4 = person;
console.log(person4);
person4.name = "小葵";
console.log(person4);
console.log(person);
person.friends[1].name = "旺旺";
console.log(person4);
console.log(person); -
获取所有的属性名
Object.keys 或者 for in
- 获取所有的属性值
Object.values
var obj = { name: "小明", age: "13", live: "red" };
console.log(Object.keys(obj)); //object.keys(定义的obj) 输出对象的每一个键名;
console.log(Object.values(obj)); //object.values(定义的obj) 输出每一个键值;
for (let i in obj) {
console.log(i); //输出键名;
console.log(obj[i]); //输出键值;
}
比较 obj
//比较两个obj字符串
var obj = { name: "小明", age: "13" };
var obj2 = { name: "小明", age: "13" };
//直接比较是false;
//想比较值的话:
console.log(JSON.stringify(obj) == JSON.stringify(obj2)); //结果为true
Promise
- 三个状态
pending(进行中)
fulfilled(成功)
reject(失败)
三个状态不可逆
-
如何定义
new Promise((reslove, reject) => {
///
// 成功之后调用 reslove
// 失败的话调用reject
}); -
Promise.all
多个 Promise 都执行完成之后触发,接收一个 promise 组成的数组作为参数
-
Promise.race
只要有一个最快的 Promise 执行完成之后触发,接收一个 promise 组成的数组作为参数
-
async/await
可以把异步的语法按照同步的方式来写,await 必须放在 async 关键词修饰的方法内使用
const p1 = new Promise((r, j) => { setTimeout(() => { r("1秒结束"); }, 1000); }); const p2 = new Promise((r, j) => { setTimeout(() => { r("2秒结束"); }, 2000); }); const p5 = new Promise((r, j) => { setTimeout(() => { r("5秒结束了"); }, 5000); }); /* p1.then((res) => { console.log(res); return "hh" }).then((res) => console.log(res)); */ /* Promise.all([p1, p5, p2]).then((res) => { console.log(res); //一起执行 }) */ /* Promise.race([p1, p5, p2]).then((res) => { console.log(res); //只执行最先的 }) */ async function LoadData() { const res1 = await p1; console.log(res1); const res2 = await p2; console.log(res2); //挨个执行 } LoadData();
node 中基础语法和常见的插件
运行环境(重点内容)
js 是编程语言
浏览器是一个 js 的运行环境,提供了很多内置的对象:bom、dom
nodejs 也是一个 js 的运行环境
npm init # 创建一个package.json文件
npm init -y # 使用默认配置创建一个package.json文件
# package.json是一个node项目的配置文件
# name不能是中文,不能和一些你项目中需要使用的模块重名
npm i xx # 安装一个依赖,安装好之后会在package.json中生成新的依赖节点,被版本信息写入
npm i xx -D # 安装开发依赖
npm uninstall xx # 卸载依赖
package.json 文件
scripts 节点,可以配置以 npm 运行的命令。我们下载一个项目之后需要先打开 package.json 文件,看下项目是怎么运行的
它里面配置的命令可以直接使用npm run
运行,除了 start 不需要加 run 之外,其他的都需要加 run
.npmrc 配置文件(可选),你可以加也可以不加.在 windows 中: c:/用户/你的用户名/.npmrc 文件
mac 或 linux: ~/.npmrc
registry=https://registry.npm.taobao.org
init.author.email=你的邮箱
init.author.name=你的名字
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
系统内置
模块引入导出
node 中模块导出方案使用的是 commonjs,通过 require 引入模块
模块化开发需要遵循的一个原则(注意事项):高内聚低耦合
-
fs
文件系统模块,用来操作文件
//fs FileSystem文件系统,可以操作电脑上的文件
const fs = require("fs");
// writeFile是一个异步操作,
// 参数一 路径
// 参数二 数据
// 参数三 回调函数
// nodejs有一个错误优先的机制,所以在node中的很多异步操作的回调函数中的第一个参数都是异常信息fs.writeFile("./data.json",
我是添加的数据
, (err) => {
if (err) {
console.log(err);
}
console.log("写文件成功");
});// 同步的方式写文件
fs.writeFileSync("./data-2.txt", "我是数据");
console.log("写文件2成功");// 异步的读文件
fs.readFile("./data.json", (err, data) => {
if (err) {
console.log(err);
}
console.log(data.toString());
console.log("读文件成功");
});// 同步的读文件
const str = fs.readFileSync("./data.json");
console.log(str.toString());//建立一个新文件
fs.mkdirSync("./tmp"); //如果建立之后在建立会报错
fs.mkdirSync("./tmp", { recursive: true }); //如果建立之后在建立也不会报错 -
path
做路径解析
const path = require("path");
// __dirname获取当前文件夹路径
console.log(__dirname);
// extname 获取扩展名
console.log(path.extname("./xx/xx/xx.png"));
// resolve 转绝对路径
console.log(path.resolve("./tmp"));//死机
// fs.mkdirSync("./tmp/tmp", { recursive: true });
// 千万别试
// 可以写一个很深的路径,导致硬盘出问题
// var paths = [];
// for (var i = 0; i < 1000; i++) {
// paths.push("tmp");
// }
// console.log("./" + paths.join("/"));
第三方
使用 npm i 安装的第三方插件
npm | Home npm(nodejs package manager)官网
-
lodash
是你需要一定要知道的一个模块,是你以后上班之后使用做多的一个插件。可以在浏览器和 node 中同时使用。它是一个 js 的工具包,封装了很多常见的 js 操作方法
-
axios
发起网络请求的。可以在浏览器或者 node 中同时使用
// https://axios-http.com/zh/docs/intro // axios.get(url, config) // 获取数据,发起get请求 // axios.post(url, data, config) // 新增数据,发起post请求 // axios.put(url, data, config) // 修改数据,发起put请求 // axios.delete(url, config) // 删除数据,发起delete请求 // 参数说明 // url 表示请求地址 // data 表示请求体中传递的数据 // config 表示配置信息 // headers 表示请求头的配置信息 // params 表示url中传递的参数 // 在nodejs中使用axios发起网络请求是没有跨域问题的 // 跨域是浏览器的安全机制引起的,node中没有浏览器,所以没有跨域 const axios = require("axios").default; // 引入插件 const fs = require("fs"); axios .get( "https://papi.jiemian.com/page/api/kuaixun/getlistmore?cid=1323kb&start_time=1639617280&page=2&tagid=1323" ) .then((res) => { // console.log(res.data); fs.writeFileSync( "./jiemian-xw.json", JSON.stringify(res.data.result.list) ); });
-
cheerio
做字符串解析的,可以在 node 中使用,把一个 html 代码解析成类似于 jQuery 的对象,可以使用以前常用的 jQ 中的所有元素选择和操作方式
const cheerio = require("cheerio");
const str = `我是一级标题哈哈😂
这是一段话
//混合使用
axios.get("https://www.xbiquge.la/").then((res) => {
// const = cheerio.load(res.data); const = cheerio.load(res.data); //解析data数据
const books = [];
("#newscontent li a").each(function () { // console.log((this).text());
// console.log((this).attr("href")); const book = {}; book.title = (this).text();
book.link = $(this).attr("href");
books.push(book);
});
console.log(books);
fs.writeFileSync("./xiaoshuo.json", JSON.stringify(books));
}); -
moment
是一个日期格式化插件
const moment = require("moment");
console.log(moment().format("YYYY-MM-DD"));
console.log(moment(5, "DD")); // 本月的第 5 天
express 框架
express 是一个基于 nodejs 的 web 开发框架(插件)
Express - 基于 Node.js 平台的 web 应用开发框架 - Express中文文档 | Express中文网
# 创建一个目录,进入
npm init -y # 创建一个package.json文件
npm i express
// main.js
const express = require("express"); // 引入模块
const app = express(); // 实例化
// 监听get请求
// 参数一 表示客户端访问的路径 http://localhost:3000/
// 参数二 表示收到客户端的请求之后的处理函数
// 参数一 表示request,请求
// 参数二 表示response,响应
app.get("/haha", (req, res) => {
res.send("你好 世界!");
});
// 表示监听当前电脑的3000端口,所有的向这个电脑发起的请求都会被以上代码处理
app.listen(3000, () => {
console.log("服务器运行在3000端口");
});
-
nodemon
这个插件的作用是可以让我们修改完 node 代码之后不需要手动的重启项目
npm i nodemon -D # 安装 # 修改package.json添加启动脚本
-
cdn 服务器
jsDelivr - A free, fast, and reliable CDN for JS and open source
https://cdn.jsdelivr.net/npm/axios@0.24.0/dist/axios.min.js
// fetch 是原生js内置的api,用来发起网络请求,返回的是一个Promise数据(体积小,节省资源)
charles
俗称花瓶,是一个网络抓包工具 Charles Web Debugging Proxy • HTTP Monitor / HTTP Proxy / HTTPS & SSL Proxy / Reverse Proxy
请求报文[必须会的]
-
请求行
第一行,包含请求方法、路径和协议版本号信息等,还有 url 参数
-
请求头
包含 cookie、content-type、用户代理等等各种信息,我们还可以把自定义的数据在请求头中传递(比如 token)
-
请求体
post 或者 put 请求传递数据的位置
post请求也有长度限制,数据大小不能超过2MB(服务器端限制)
GET 请求报文
GET /api/v1/books?id=123 HTTP/1.1
Host: 192.168.17.96:3000
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6
Connection: keep-alive
POST 请求的报文
POST /api/v1/books HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: 5922939d-c10e-49d6-8511-fbc1744408f6
Host: 192.168.17.96:3000
Accept-Encoding: gzip, deflate, br
Content-Length: 26
Connection: keep-alive
{
"name": "赛文"
}
post 请求传递一个 url 编码格式的数据
POST /api/v1/books HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: 86f32daf-0959-430c-94af-6295969e52c6
Host: 192.168.17.96:3000
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 23
Connection: keep-alive
name=%E9%93%B6%E6%B2%B3
POST /api/v1/books HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: f5a3f3be-2232-4262-8288-a50f2e03fd5b
Host: 192.168.17.96:3000
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=--------------------------559173827354490975907797
Content-Length: 18623
Connection: keep-alive
----------------------------559173827354490975907797
Content-Disposition: form-data; name="file"; filename="3.jpg"
Content-Type: image/jpeg
RIFFìG
请求头中的 content-type 属性
它标识了请求体中数据的格式,服务器端代码根据这个属性实现不同的解析操作,常见到的有三种
-
application/x-www-form-urlencoded
请求体中的数据是 url 编码的,在使用 jQuery 发起 ajax 请求的时候,默认是这种格式的数据
-
application/json
请求体中的数据是 json 编码的,在使用 axios 发请求的时候默认是这种格式的
-
multipart/form-data
上传文件的时候使用
在很多时候需要和你们公司的服务器端开发约定好传递的数据格式,要不然就会出现数据无法解析的问题
服务器端返回给我们的真实的响应数据
HTTP/1.1 200 OK
X-Powered-By: Express
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Fri, 17 Dec 2021 01:13:47 GMT
ETag: W/"12b-17dc5f3c6e0"
Content-Type: text/html; charset=UTF-8
Content-Length: 299
Date: Fri, 17 Dec 2021 01:13:52 GMT
Keep-Alive: timeout=5
Proxy-Connection: keep-alive
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>这是首页</h1>
</body>
</html>
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 2
ETag: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
Date: Fri, 17 Dec 2021 01:12:34 GMT
Keep-Alive: timeout=5
Proxy-Connection: keep-alive
[]
文件上传
前端把文件通过上传接口传给服务器,服务器返回一个可以访问的网络路径。然后前端调用数据存储接口,把这个地址存储服务器的数据库中。文件是单独存在文件夹中的
const formData = new FormData(); // FormData是原生js内置的api,可以帮我们组织一个表单数据
mongodb和mongoose插件
Download MongoDB Community Server | MongoDB 下载地址
数据持久化和数据库
数据持久化就是把数据永久的保存起来,除非删除,否则哪怕我们重启项目数据依然在。常见的数据持久化方法有:存文件、存数据库
数据库:数据库是一个软件,它的作用是持久化的存储文件数据。数据库使用的是一门独立的开发语言(SQL结构化查询语句)。我们常见的数据库有:
mysql:免费开源的跨平台数据库
mongodb:开源的跨平台数据库
sqlserver:只能在windows中使用
oracle:跨平台的大型数据库,很贵
pgsql:开源的跨平台数据库,目前使用比较广泛。在GIS系统中使用较多,因为其内置了很多坐标运算方法
sqlite:小型的文件数据库,在手机APP开发的时候使用比较多
access:office集成的数据库,微软系列的
redis:内存数据库,可以进行快速的数据存储。现在使用比较多,主要在项目做性能优化的时候使用,方便快速的数据存取操作,使用key-value的形式存储数据
mongoose
mongoose是一个mongodb中连接数据库的插件,可以让我们不需要学习数据库操作语句,直接使用js代码已对象的方式操作数据库
npm i mongoose # 安装
常用的api列出来
save 保存
find 查找,返回一个集合
findOne 查找一个
findById 根据id查找
findByIdAndRemove 根据id删除一个
findByidAndUpdate 根据id查找并修改
count 统计数量
insertMany 插入多个
RESTFul风格的api
是你以后上班之后比较常见的一种服务器端提供api的风格,这只是一个参考,建议做服务器端接口开发的时候大家遵循。但是实际应用的时候会有些许的差异
服务器端渲染
BSR(CSR):浏览器端(客户端)渲染
SSR:服务器端渲染
express应用生成器
可以使用官方提供的代码模板,快速的生成项目
模板引擎
作用是代替字符串拼接,类似模板字符串。有一些内置的替换字符,都是固定的写法
ejs是我们需要学会的第一个模板引擎,他有常用的三个语法
<% js表达式 %>
<%= 'sss' %> 输入内容
<%- 富文本内容 %> 使用-的时候,如果文本中存在html字符串会自动进行解析
服务器端接口
websockets
实时获取服务器中的最新数据,应用场景:数据监控大屏、外卖或者其他平台的实时消息推送
轮询
是在页面中制作一个定时器,不停的向服务器发送请求
存在的问题:
- 延时,数据不是实时更新的,和我们请求的频率有关系
- 会增加服务器额外的压力,在没有数据更新的情况下也在不停的发请求
- 客户端页面定时器用多了会出现不准以及卡顿的问题
websocket
长连接,当客户端和服务器端建立起连接之后,服务器端有最新的数据的时候会主动的向客户端推送
Socket.IO 是node中创建ws服务器连接的插件
npm i socket.io