ajax

1.AJAX概念和axios

什么是AJAX?

使用浏览器的 XMLHttpRequest 对象 与服务器通信

axios用法

1 引入axios.js文件

2 具体用法

url:资源定位符

params:请求参数

method:请求方法

data:请求体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
      axios({
url:' http://hmajax.itheima.net/api/area',
params:{
pname,
cname,
}
})

axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
console.log(result)
console.log(result.data.message)
}).catch(error => {
console.log(error)
console.log(error.response.data.message)
})

2.URL和URL参数查询

URL概念和组成

什么是 URL ?

  • 统一资源定位符,简称网址,用于定位网络中的资源(资源指的是:网页,图片,数据,视频,音频等等)

URL的组成?

  • 协议,域名,资源路径

URL参数查询

参数查询语法?

URL参数查询类似axios用请求方法get 请求参数params

URL中的端口号

端口号的作用:标记服务器里对应的服务程序值为(0-65535 之间的任意整数)

http 协议,默认访问的是 80 端口

常用端口如 数据库3306 ssh22

注意:0-1023 和一些特定的端口号被占用,我们自己编写服务程序请避开使用

3.请求报文与响应报文

请求报文

请求报文:是浏览器按照协议规定发送给服务器的内容,例如刚刚注册用户时,发起的请求报文:

这里的格式包含:

  • 请求行:请求方法,URL,协议
  • 请求头:以键值对的格式携带的附加信息,比如:Content-Type(指定了本次传递的内容类型)
  • 空行:分割请求头,空行之后的是发送给服务器的资源
  • 请求体:发送的资源

响应报文

响应报文的组成:

  • 响应行(状态行):协议,HTTP响应状态码,状态信息
  • 响应头:以键值对的格式携带的附加信息,比如:Content-Type(告诉浏览器,本次返回的内容类型)
  • 空行:分割响应头,控制之后的是服务器返回的资源
  • 响应体:返回的资源

HTTP 响应状态码

1xx 信息响应

  • 100 Continue: 服务器已接收到请求头部,客户端应继续发送请求主体(例如,在发送一个较大的请求主体之前)。
  • 101 Switching Protocols: 服务器同意客户端请求更改协议(例如,从 HTTP 升级到 WebSocket)。

2xx 成功响应

  • 200 OK: 请求成功。响应的内容随请求方法的不同而不同。
  • 201 Created: 请求已成功并且在服务器上创建了新的资源。
  • 202 Accepted: 服务器已接受请求,但尚未处理完成。
  • 204 No Content: 服务器成功处理了请求,但没有返回任何内容。

3xx 重定向

  • 301 Moved Permanently: 请求的资源已永久移动到新的 URL。客户端应使用新的 URL 进行请求。
  • 302 Found: 请求的资源临时移动到新的 URL。客户端应使用原始的 URL 进行后续请求。
  • 304 Not Modified: 请求的资源未修改。客户端可以使用缓存的版本。

4xx 客户端错误

  • 400 Bad Request: 服务器无法理解请求,通常是因为请求语法错误。
  • 401 Unauthorized: 请求需要用户认证。
  • 403 Forbidden: 服务器理解请求,但拒绝执行。
  • 404 Not Found: 服务器找不到请求的资源。
  • 405 Method Not Allowed: 请求方法不被允许。
  • 408 Request Timeout: 服务器等待客户端发送请求时间过长。

5xx 服务器错误

  • 500 Internal Server Error: 服务器遇到未预期的情况,无法完成请求。
  • 501 Not Implemented: 服务器不支持请求的方法。
  • 502 Bad Gateway: 服务器作为网关或代理,从上游服务器接收到无效响应。
  • 503 Service Unavailable: 服务器暂时无法处理请求,通常是因为服务器过载或维护。
  • 504 Gateway Timeout: 服务器作为网关或代理,未能及时从上游服务器接收到响应。

4.Json字符串与js对象

json字符串的展开运算符…

1
2
3
4
5
6
7
const jsonString = '{"name": "John", "age": 30, "city": "New York"}';
const obj = JSON.parse(jsonString);

const newObj = { ...obj, country: 'USA' };

console.log(newObj);
// 输出: { name: 'John', age: 30, city: 'New York', country: 'USA' }

JSON.stringify(obj)

接受一个 JavaScript 对象或数组,并返回一个 JSON 字符串。

JSON.parse(jsonString)

接受一个 JSON 字符串,并返回一个 JavaScript 对象或数组。

Object.keys(obj)

是 JavaScript 中的一个内置方法,用于返回一个给定对象的可枚举属性名(即键)的数组。

获得对象obj某个键key的值 obj[key]

5.Ajax原理

ajax原理

ajax原理即xhr

XMLHttpRequest的使用四个步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 目标:使用XMLHttpRequest对象与服务器通信
* 1. 创建 XMLHttpRequest 对象
* 2. 配置请求方法和请求 url 地址
* 3. 监听 loadend 事件,接收响应结果
* 4. 发起请求
*/
// 1. 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 2. 配置请求方法和请求 url 地址
xhr.open('请求方法','url地址');
// 3. 监听 loadend 事件,接收响应结果
xhr.addEventListener('loadend', () => {

});
// 4. 发起请求
xhr.send();

xmlhttprequest参数查询

简单参数查询即第二步里,url写成url?参数1=值1&参数2=值2这种格式

URLSearchParams API

URLSearchParams API 可以将js对象转成参数查询对象

示例代码

1
2
3
4
5
6
7
8
9
10
const qObj = {
pname,
cname,
}
const paramsObj = new URLSearchParams(qObj);
const queryString = paramsObj.toString();
console.log(queryString);

const xhr = new XMLHttpRequest;
xhr.open('GET',`http://hmajax.itheima.net/api/area?${queryString}`);

请求参数 body参数 &设置请求头API setRequestHeader

对请求参数要求格式是JSON时 使用API setRequestHeader设置请求头

示例代码

1
xhr.setRequestHeader('content-type','application/json');

传递请求参数

示例代码

1
2
3
4
5
6
const userObj = {
username: 'winter1245464',
password: 'winterlee446'
}
const userObjStr = JSON.stringify(userObj);
xhr.send(userObjStr);

6.promise

promise概念

Promise 对象用于表示一个异步操作的最终完成(或失败)及其结构值

promise使用步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 创建 Promise 对象
const p = new Promise((resolve, reject) => {
// 2. 执行异步任务-并传递结果
// 成功调用: resolve(值) 触发 then() 执行
// 失败调用: reject(值) 触发 catch() 执行
})

// 3. 接收结果
p.then(result => {
// 成功
}).catch(error => {
// 失败
})

Promise 有哪三种状态?

每个 Promise 对象必定处于以下三种状态之一(fulfilled和rejected后不可改变)

  1. 待定(pending):初始状态,既没有被兑现,也没有被拒绝
  2. 已兑现(fulfilled):操作成功完成
  3. 已拒绝(rejected):操作失败

错误对象打印

console.dir(error)

7.封装简易axios

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function myAxios(config) {
return new Promise((resolve, reject) => {
// 创建XHR对象
const xhr = new XMLHttpRequest()
// 如果有查询参数 拼接到url上
if (config.params) {
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
config.url += `?${queryString}`
}
// 配置请求方法和请求url地址
xhr.open(config.method || 'GET', config.url)
// 异步任务 resolve reject
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
//请求参数传递 请求头设置
if (config.data) {
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
xhr.send()
}
})
}

8.同步 异步

同步代码 异步代码

  1. 同步代码:逐行执行,需原地等待结果后,才继续向下执行

  2. 异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发回调函数传递结果

JS 中有哪些异步代码?

setTimeout / setInterval,事件,AJAX

回调地狱

在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱

Promise链式调用

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
doSomething()
.then(function(result1) {
return doSomethingElse(result1);
})
.then(function(result2) {
return doAnotherThing(result2);
})
.then(function(result3) {
return doFinalThing(result3);
})
.then(function(result4) {
console.log('Done', result4);
})
.catch(function(error) {
console.error('Something went wrong', error);
});

async函数和await

使用方法:在async函数内,使用async函数内,使用await关键字取代then函数,等待获取promise对象成功状态的结果值

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. 定义async修饰函数
async function getData() {
// 2. await等待Promise对象成功的结果
const pObj = await axios({url: 'http://hmajax.itheima.net/api/province'})
const pname = pObj.data.list[0]
const cObj = await axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})
const cname = cObj.data.list[0]
const aObj = await axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
const areaName = aObj.data.list[0]


document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = areaName
}

getData()

捕获错误 try…catch

try 和 catch 的作用:语句标记要尝试的语句块,并指定一个出现异常时抛出的响应

1
2
3
4
5
6
try {
// 要执行的代码
} catch (error) {
// error 接收的是,错误消息
// try 里代码,如果有错误,直接进入这里执行
}

遇到错误直接跳出,不再往下执行

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 目标:async和await_错误捕获
*/
async function getData() {
// 1. try包裹可能产生错误的代码
try {
const pObj = await axios({ url: 'http://hmajax.itheima.net/api/province' })
const pname = pObj.data.list[0]
const cObj = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
const cname = cObj.data.list[0]
const aObj = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
const areaName = aObj.data.list[0]

document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = areaName
} catch (error) {
// 2. 接着调用catch块,接收错误信息
// 如果try里某行代码报错后,try中剩余的代码不会执行了
console.dir(error)
}
}

getData()

事件循环(EventLoop)

事件循环:执行代码和收集异步任务的模型,在调用栈空闲时,反复调用任务队列里回调函数执行机制

js单线程 浏览器多线程

步骤:

  1. js执行同步代码,遇到异步代码交给宿主浏览器环境执行
  2. 浏览器异步有结果后,会把回调函数放入任务队列排队
  3. 当调用栈空闲后,反复调用任务队列里的回调函数

宏任务与微任务

异步任务分为宏任务微任务

宏任务:由浏览器环境执行的异步代码

微任务:由JS引擎环境执行的异步代码

宏任务与微任务的具体划分

执行顺序:同步代码->微任务->宏任务

Promise.all 静态方法

概念:合并多个 Promise 对象,等待所有同时成功完成(或某一个失败),做后续逻辑

语法

1
2
3
4
5
6
const p = Promise.all([Promise对象, Promise对象, ...])
p.then(result => {
// result 结果: [Promise对象成功结果, Promise对象成功结果, ...]
}).catch(error => {
// 第一个失败的 Promise 对象,抛出的异常对象
})

9.一些第三方库

serialize.js收集表单数据

  1. 引入form-serialize.js

  2. 获取表单元素(表单元素要有name属性作为收集数据中的属性名)

    示例代码

    const form = document.querySelector('.art-form');

  3. 配置对象

    • hash:
      • true - 收集出来的是一个 JS 对象结构
      • false - 收集出来的是一个查询字符串格式
    • empty:
      • true - 收集空值
      • false - 不收集空值

​ 示例代码:const data = serialize(form, { hash: true, empty: true})

富文本编辑器-wangEditor插件

1.引入wangEditor的css样式

2.html部分

1
2
3
4
5
6
7
8
9
10
<div>
<label for="">内容:</label>
<!-- 富文本编辑器位置 -->
<div id="editor—wrapper">
<div id="toolbar-container"><!-- 工具栏 --></div>
<div id="editor-container"><!-- 编辑器 --></div>
</div>
<!-- 记录富文本内容-用于表单收集 -->
<textarea name="content" class="publish-content" hidden></textarea>
</div>

3.js部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 富文本编辑器
// 创建编辑器函数,创建工具栏函数
const { createEditor, createToolbar } = window.wangEditor

const editorConfig = {
placeholder: 'Type here...',
onChange(editor) {
const html = editor.getHtml()
console.log('editor content', html)
// 也可以同步到 <textarea>
document.querySelector('.publish-content').value = html;
}
}

const editor = createEditor({
selector: '#editor-container',
html: '<p><br></p>',
config: editorConfig,
mode: 'default', // or 'simple'
})

const toolbarConfig = {}

const toolbar = createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default', // or 'simple'
})

10.axios

axios配置基地址

1
axios.defaults.baseURL = 'http://geek.itheima.net'

配置后axios请求时都会baseURL + url

token 访问权限令牌

概念:访问权限的令牌,本质上是一串字符串

创建:正确登录后,由后端签发并返回

作用:判断是否有登录状态等,控制访问权限

注意:前端只能判断 token 有无,而后端才能判断 token 的有效性

axios传递请求头参数

参数headers

1
2
3
4
5
6
axios({
url: '目标资源地址',
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
})

axios请求拦截器

请求拦截器是发起请求到服务器前被调用的一个函数,对请求参数进行设置。

有公共配置和设置时,统一设置在请求拦截器中

示例代码

1
2
3
4
5
6
7
8
9
axios.interceptors.request.use(function (config) {
const token = location.getItem('token')
token && config.headers.Authorization = `Bearer ${token}`
// 在发送请求之前做些什么
return config
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error)
})

axios响应拦截器

axios 响应拦截器:响应回到 then/catch 之前,触发的拦截函数,对响应结果统一处理

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么,例如:直接返回服务器的响应结果对象
const result = response.data
return result;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么,例如:判断响应状态为 401 代表身份验证失败
if (error?.response?.status === 401) {
alert('登录状态过期,请重新登录')
window.location.href = '../login/index.html'
}
return Promise.reject(error);
});

11.正则表达式

正则表达式(Regular Expression, 简称regex或regexp)是一种强大的字符串匹配和处理工具,用于搜索,匹配和操作字符串。正则表达式使用特定的语法规则来描述和匹配字符串模式。

基本概念

  • 字面字符:普通字符在正则表达式中代表它们自己的值,如a匹配字母a
  • 元字符:具有特殊意义的字符,用于指定复杂的匹配规则,如.*?+[]等。

常用符号

  1. .(点号):匹配除换行符以外的任意单个字符。
    • 示例:a.b可以匹配aaba1b等。
  2. *(星号):匹配前面的元素零次或多次。
    • 示例:a*b可以匹配babaab等。
  3. +(加号):匹配前面的元素一次或多次。
    • 示例:a+b可以匹配abaabaaab等,但不匹配b
  4. ?(问号):匹配前面的元素零次或一次。
    • 示例:a?b可以匹配bab
  5. [](方括号):匹配方括号内的任意一个字符。
    • 示例:[abc]可以匹配abc中的任何一个。
  6. [^](脱字符在方括号内):匹配不在方括号内的任意一个字符。
    • 示例:[^abc]可以匹配除abc之外的任何一个字符。
  7. |(竖线):表示逻辑或,用于匹配多个选项中的一个。
    • 示例:a|b可以匹配ab
  8. ()(小括号):用于分组,分组可以作为一个整体使用量词,也可以提取匹配的子字符串。
    • 示例:(abc)+可以匹配abcabcabc等。
  9. \(反斜杠):用于转义元字符,使其作为字面字符使用。
    • 示例:\.可以匹配.字符。

预定义字符类

  1. **\d**:匹配任意一个数字,相当于[0-9]
    • 示例:\d可以匹配012等。
  2. **\D**:匹配任意一个非数字字符,相当于[^0-9]
    • 示例:\D可以匹配ab@等。
  3. **\w**:匹配任意一个字母、数字或下划线,相当于[a-zA-Z0-9_]
    • 示例:\w可以匹配a1_等。
  4. **\W**:匹配任意一个非字母、非数字、非下划线的字符,相当于[^a-zA-Z0-9_]
    • 示例:\W可以匹配@# 等。
  5. **\s**:匹配任意一个空白字符(包括空格、制表符、换页符等)。
    • 示例:\s可以匹配空格、 \t等。
  6. **\S**:匹配任意一个非空白字符。
    • 示例:\S可以匹配a1@等。

常用示例

  1. 匹配邮箱地址

    1
    [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
  2. 匹配电话号码(假设为10位数字):

    1
    \d{10}
  3. 匹配日期(格式为YYYY-MM-DD)

    1
    \d{4}-\d{2}-\d{2}
  4. 匹配URL

    1
    https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/[\w.-]*)*

12.Node.js

了解Nodejs

nodejs的作用

1.编写后端程序,提供数据和网页资源

  1. 作为前端工程化的工具,翻译压缩整合代码等,提高开发效率

Node.js 与浏览器环境的 JS 最大区别

Node.js 环境中没有 BOM 和 DOM,但是也用 JS 语法

fs模块-文件系统交互

fs模块用于与文件系统 交互

使用步骤

1.加载模块对象,得到fs对象

1
const fs = require('fs')

2.写入文件内容

1
2
3
fs.writeFile('文件路径', '写入内容', (err) => {

})

3.读取文件内容

1
2
3
fs.readFile('文件路径', (err, data) => {
//data是文件内容的Buffer数据流
})

path模块-路径处理

nodejs的相对路径是?

nodejs的相对路径是终端所在文件夹的相对路径,而不是js文件本身所在文件夹的路径

所以用path模块,获得绝对路径解决

使用步骤

1.加载path模块

1
const path = require('path')

2.获取该js文件所在文件夹的绝对路径并拼接

1
const pathStr = path.join(__dirname,'...','...')

http模块-创建web服务

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 目标:基于 http 模块创建 Web 服务程序
* 1.1 加载 http 模块,创建 Web 服务对象
* 1.2 监听 request 请求事件,设置响应头和响应体
* 1.3 配置端口号并启动 Web 服务
* 1.4 浏览器请求(http://localhost:3000)测试
*/
// 1.1 加载 http 模块,创建 Web 服务对象
const http = require('http')
const server = http.createServer()
// 1.2 监听 request 请求事件,设置响应头和响应体
server.on('request', (req, res) => {
// 设置响应头-内容类型-普通文本以及中文编码格式
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
// 设置响应体内容,结束本次请求与响应
res.end('欢迎使用 Node.js 和 http 模块创建的 Web 服务')
})
// 1.3 配置端口号并启动 Web 服务
server.listen(3000, () => {
console.log('Web 服务启动成功了')
})

express模块-创建web服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express');
const app = express();

// 监听请求并设置响应头和响应体
app.get('/', (req, res) => {
// 设置响应头-内容类型-普通文本以及中文编码格式
res.set('Content-Type', 'text/plain;charset=utf-8');
// 设置响应体内容,结束本次请求与响应
res.send('欢迎使用 Node.js 和 Express 框架创建的 Web 服务');
});

// 配置端口号并启动 Web 服务
app.listen(3000, () => {
console.log('Web 服务启动成功了');
});

nodejs模块化

什么是模块化?

每个文件都是独立的模块

commonjs 导入导出语法

导出

1
2
3
module.exports = {
对外属性名: 模块内私有变量
}

导入

1
2
3
const 变量名 = require('模块名或路径')
// Node.js 环境内置模块直接写模块名(例如:fs,path,http)
// 自定义模块:写模块文件路径(例如:./utils.js)

nodejs默认支持commonJS标准

ECMAScript标准的导入导出

ECMAScript标准 默认导入导出语法

使用该标准前 先设置package.json 并设置 {“type”: module}

导出语法

1
2
3
export default : {
对外属性名: 模块内私有变量
}

导入语法

1
import 变量名 from '模块名或路径'

ECMAScript标准 命名导入导出语法

导出语法

1
2
// export 修饰定义语句
export const baseURL = 'http://hmajax.itheima.net'

导入语法

1
import {同名变量} from '模块名或路径'

与默认导出如何选择:

  • 按需加载,使用命名导出和导入
  • 全部加载,使用默认导出和导入

包的概念

包:将模块,代码,其他资料整合成的一个文件夹

包分类:

​ 项目包:主要用于编写项目和业务逻辑

​ 软件包:封装工具和方法进行使用

注意事项:

  • 需要有package.json记录软件包名字,作者,入口文件
  • 默认引入的是包文件节下的 index.js 模块文件里导出的对象,如果没有 index.js 文件,则会引入 package.json 里 main 属性指定的文件模块导出的对象

入口文件应该集中工具模块的方法,再统一向外暴露

npm

初始化清单文件package.json命令

npm init -y

下载软件包命令 生产环境所需依赖

npm i 包名称

下载软件包命令 开发环境所需依赖

npm i 包命称 --save-dev

全局下载软件包命令

npm i 报名称 -g

npm安装所有依赖命令

npm i

使用情景:拿到它人项目后,没有包,根据package.json下载

pnpm

更快,更节省空间

安装pnpm

npm i -g pnpm

创建vue项目

pnpm create vue

安装所有依赖

pnpm install

安装软件包

pnpm add 包名

安装开发依赖

pnpm add 包名 -D

卸载某个包

pnpm remove 包名

13.Webpack

webpack概念和使用步骤

webpack是一个静态模块打包工具

静态模块:编写代码过程中的,html,css, js,图片等固定内容的文件

webpack打包步骤

1.先在项目文件夹下,初始化包环境,得到package.json文件

npm init -y

2.下载webpack webpack-cli到项目 (版本独立)

npm i webpack webpack --save-dev

–save-dev的意思是开发依赖

3.package.json中将webpack配置到自定义命令

1
2
3
4
5
6
7
{
...
"srcipts" : {
"build": "webpack"
}
...
}

4.运行命令

npm run build

weback修改入口和出口

修改入口和出口以改变打包设置

步骤:

  1. 在项目根目录,新建webpack.config.js文件

  2. 设置导出配置对象filename,配置入口entry,出口文件路径path

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const path = require('path')

    module.exports = {
    entry: path.resolve(__dirname, 'src/login/index.js'),
    output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './login/index.js',
    clean: 'true' // 清空输出目录
    }
    }
  3. npm run build

webpack生成html

webpack默认只能打包js文件,打包html需用webpack插件 html-webpack-plugin

步骤:

  1. 下载 html-webpack-plugin 本地软件包到项目中

    1
    npm i html-webpack-plugin --save-dev
  2. 配置 webpack.config.js 让 Webpack 拥有插件功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // ...
    const HtmlWebpackPlugin = require('html-webpack-plugin')

    module.exports = {
    // ...
    plugins: [
    new HtmlWebpackPlugin({
    template: './public/login.html', // 模板文件
    filename: './login/index.html' // 输出文件
    })
    ]
    }
  3. 指定以 public/login.html 为模板复制到 dist/login/index.html,并自动引入其他打包后资源

webpack打包css到js

最后结果是 css在js里

用到了webpack加载器 识别更多模块内容

步骤:

  1. 准备 css 文件引入到 src/login/index.js 中(压缩转译处理等)

    1
    2
    3
    // 准备 css 代码,并引入到 js 中
    import 'bootstrap/dist/css/bootstrap.min.css'
    import './index.css'

    注意:这里只是引入代码内容让 Webpack 处理,不需定义变量接收在 JS 代码中继续使用,所以没有定义变量接收

  2. 下载 css-loader 和 style-loader 本地软件包

    1
    npm i css-loader style-loader --save-dev
  3. 配置 webpack.config.js 让 Webpack 拥有该加载器功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // ...

    module.exports = {
    // ...
    module: { // 加载器
    rules: [ // 规则列表
    {
    test: /\.css$/i, // 匹配 .css 结尾的文件
    use: ['style-loader', 'css-loader'], // 使用从后到前的加载器来解析 css 代码和插入到 DOM
    }
    ]
    }
    };
  4. 打包后运行 dist/login/index.html 观察效果,看看准备好的样式是否作用在网页上

webpack提取css代码为独立文件

用到插件 mini-css-extract-plugin

步骤:

  1. 下载 mini-css-extract-plugin 插件软件包到本地项目中

    1
    npm i --save-dev mini-css-extract-plugin
  2. 配置 webpack.config.js 让 Webpack 拥有该插件功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // ...
    const MiniCssExtractPlugin = require("mini-css-extract-plugin")

    module.exports = {
    // ...
    module: {
    rules: [
    {
    test: /\.css$/i,
    // use: ['style-loader', 'css-loader']
    use: [MiniCssExtractPlugin.loader, "css-loader"],
    },
    ],
    },
    plugins: [
    // ...
    new MiniCssExtractPlugin()
    ]
    };
  3. 打包后观察效果

  4. 注意:不能和 style-loader 一起使用

  5. 好处:css 文件可以被浏览器缓存,减少 JS 文件体积,让浏览器并行下载 css 和 js 文件

webpack打包less代码

让webpack能够打包less代码

用到 加载器 less-loader

步骤

  1. 建立less文件,将less样式引入到src/login/index.js

    import './index.less'

  2. 下载less和less-loader 本地软件包

    npm i less less-loader --save-dev

  3. 配置webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // ...

    module.exports = {
    // ...
    module: {
    rules: [
    // ...
    {
    test: /\.less$/i,
    use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
    }
    ]
    }
    }

webpack打包图片

webpack有内置资源模块的打包

步骤

1.配置 webpack.config.js 让 Webpack 拥有打包图片功能

占位符 【hash】对模块内容做算法计算,得到映射的数字字母组合的字符串

占位符 【ext】使用当前模块原本的占位符,例如:.png / .jpg 等字符串

占位符 【query】保留引入文件时代码中查询参数(只有 URL 下生效)

2.注意:判断临界值默认为 8KB

大于 8KB 文件:发送一个单独的文件并导出 URL 地址

小于 8KB 文件:导出一个 data URI(base64字符串)

webpack搭建开发环境

webpack-dev-server可以让每次改动代码时,自动检测变化热更新到网页

步骤

  1. 下载webpack-dev-server软件包

  2. 配置自定义命令,设置打包模式为开发模式

    1
    2
    3
    4
    5
    6
    // ...

    module.exports = {
    // ...
    mode: 'development'
    }
    1
    2
    3
    4
    "scripts": {
    // ...
    "dev": "webpack serve --mode=development"
    },

:默认public文件夹为服务器根目录 也会把webpack.config.js里设置的output放到内存

放到内存里的output结果和output目录里的并不一样

可以在public里设置 跳转到 output目录即可

–open每次代码刷新自动打开网页

webpack的打包模式

打包模式的分类

模式名称 模式名字 特点 场景
开发模式 development 调试代码,实时加载,模块热替换等 本地开发
生产模式 production 压缩代码,资源优化,更轻量等 打包上线

如何设置打包模式?

方式1:在 webpack.config.js 配置文件设置 mode 选项

1
2
3
4
5
6
// ...

module.exports = {
// ...
mode: 'production'
}

方式2:在 package.json 命令行设置 mode 参数

1
2
3
4
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack serve --mode=development"
},

:命令行设置的优先级高于配置文件中的,推荐用命令行设置

webpack打包模式的应用

示例需求:在开发模式下用style-loader内嵌,在生产模式独立css代码

方案:

方案1:webpack.config.js 配置导出函数,但是局限性大(只接受 2 种模式)

方案2:借助 cross-env (跨平台通用)包命令,设置参数区分环境

方案3:配置不同的 webpack.config.js (适用多种模式差异性较大情况)

步骤:

1.下载cross-env软件包

npm i cross=env --save-dev

2.配置自定义命令,传入参数和值(会绑定到 process.env 对象下)

3.在 webpack.config.js 区分不同环境使用不同配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module: {
rules: [
{
test: /\.css$/i,
// use: ['style-loader', "css-loader"],
use: [process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
}
],
},

前端注入环境变量

问题:

cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV

解决:

使用 Webpack 内置的 DefinePlugin 插件

使用方式

配置 webpack.config.js 中给前端注入环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ...
const webpack = require('webpack')

module.exports = {
// ...
plugins: [
// ...
new webpack.DefinePlugin({
// key 是注入到打包后的前端 JS 代码中作为全局变量
// value 是变量对应的值(在 corss-env 注入在 node.js 中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
}

应用场景

前端项目中,开发模式下打印语句生效,生产模式下打印语句失效

webpack 开发环境调错 source map

解决问题:代码被压缩后,无法确认源代码的位置

注:只用于开发环境,不在生产环境使用

1
2
3
4
module.exports = {
// ...
devtool: 'inline-source-map'
}

设置解析路径别名 alias

例:

原来路径如下:

1
import { checkPhone, checkCode } from '../src/utils/check.js'

配置解析别名:在 webpack.config.js 中设置

1
2
3
4
5
6
7
8
9
10
// ...

const config = {
// ...
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}

这样我们以后,引入目标模块写的路径就更简单了

1
import { checkPhone, checkCode } from '@/utils/check.js'

优化cdn使用

[bootcdn](BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务) 查到cdn链接

unpkg 查到其他链接

npmjs 查到所有cdn

优化:开发模式使用第三方库,生产模式使用cdn加载引入

1.在 html 中引入第三方库的 CDN 地址 并用模板语法判断

1
2
3
<% if(htmlWebpackPlugin.options.useCdn){ %>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<% } %>

2.配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)

1
2
3
4
5
6
7
8
9
if(process.env.NODE_ENV === 'production') {
//外部扩展 防止生产模式时 import的包被打包进来
config.externals = {
//key: import from 语句后面的字符串
//value:留在原地的全局变量
'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
'axios': 'axios'
}
}
1
2
3
4
5
6
7
8
9
10
11
// ...
const config = {
// ...
plugins: [
new HtmlWebpackPlugin({
// ...
// 自定义属性,在 html 模板中 <%=htmlWebpackPlugin.options.useCdn%> 访问使用
useCdn: process.env.NODE_ENV === 'production'
})
]
}

webpack 多页面打包

概念:

单页面:单个 html 文件,切换 DOM 的方式实现不同业务逻辑展示, Vue/React 会用到

多页面:多个 html 文件,切换页面实现不同业务逻辑展示

步骤

1.准备页面源码 改成模块化的导入导出方式

​ 1.css代码包可以用cdn引入,但是自己写的css代码要模块化导入导出到index.js里

​ 2.js代码包可以利用模板语法,生产模式引入cdn,开发模式用自己下到本地的包。自己写的js代码要模块化导入导出到index.js里

2.修改webpack.config.js 添加入口和出口和多页面的设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ...
const config = {
entry: {
'模块名1': path.resolve(__dirname, 'src/入口1.js'),
'模块名2': path.resolve(__dirname, 'src/入口2.js'),
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './[name]/index.js'
}
plugins: [
new HtmlWebpackPlugin({
template: './public/页面2.html', // 模板文件
filename: './路径/index.html', // 输出文件
chunks: ['模块名2']
})
new HtmlWebpackPlugin({
template: './public/页面2.html', // 模板文件
filename: './路径/index.html', // 输出文件
chunks: ['模块名2']
})
]
}

优化-分割公共代码

将多个页面引用的公共代码提取

配置 webpack.config.js 的 splitChunks 分割功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ...
const config = {
// ...
optimization: {
// ...
splitChunks: {
chunks: 'all', // 所有模块动态非动态移入的都分割分析
cacheGroups: { // 分隔组
commons: { // 抽取公共模块
minSize: 0, // 抽取的chunk最小大小字节
minChunks: 2, // 最小引用数
reuseExistingChunk: true, // 当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用
name(module, chunks, cacheGroupKey) { // 分离出模块文件名
const allChunksNames = chunks.map((item) => item.name).join('~') // 模块名1~模块名2
return `./js/${allChunksNames}` // 输出到 dist 目录下位置
}
}
}
}

14.json-server

json-server 是一个用于快速搭建 RESTful API 的工具,它能够将一个 JSON 文件模拟成一个完整的 API 服务。这个工具非常适合用于前端开发过程中,需要一个简单的后端服务来提供数据和测试 API 的场景。

使用步骤

  1. 安装全局工具 json-server (全局工具仅需要安装一次)
1
yarn global add json-server 或 npm i json-server  -g
  1. 代码根目录新建一个 db 目录
  2. 将资料 index.json 移入 db 目录
  3. 进入 db 目录,执行命令,启动后端接口服务 (使用–watch 参数 可以实时监听 json 文件的修改)
1
json-server  --watch  index.json