前端其它
AJAX
AJAX(Asynchronous JavaScript And XML )是一种使用 XMLHttpRequest 技术构建更复杂,动态的网页的编程实践。(来自mdn)
axios使用
1 |
|
url
url即资源定位符(或统一定位器、定位地址、URL地址),简称网址,用于访问网络上的资源
- url组成:协议 域名 资源路径
- 协议:规定浏览器和服务器之间传输数据的格式
- 域名:即服务器的位置
- 资源路径:资源在服务器下的具体位置
- 查询参数:
?a=x&b=x
axios提供了params选项作为查询参数,此种情况下,axios会将参数名和值拼接成类似?a=x&b=x
的样式
请求方法
GET POST PUT DELETE PATCH
axios请求数据的配置,指定method和data属性,get请求可以省略method,提交的数据放在data中,params中写查询参数
1 |
|
错误处理
只要在之后的函数中添加catch即可
1 |
|
请求报文
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容
- 组成
- 请求行:包含请求方法、url 协议
- 请求头:以键值对格式携带的附加信息,如Content-Type
- 空行:分隔请求头,空行之后用来存储发送给服务器的数据
- 请求体:发送的资源
- 错误排查
响应报文
请求报文:浏览器按照HTTP协议要求的格式,返回给服务器的内容
- 组成:相应行、响应头、空行、响应体(返回的资源)
- 响应状态码:1xx表示信息 2xx表示成功 3xx表示重定向消息 4xx表示客户端错误 5xx表示服务端错误 404服务器找不到资源
JS库form-serialize插件中的serialize()函数 可以快速收集表单元素的值
- 使用form-serialize
-
使用该库,需要保证表单中的input都要有name属性,以便serialize函数获得
-
参数1:要获取的 form 表单标签对象(要求表单元素需要有 name 属性-用来作为收集的数据中属性名)
-
参数2:配置对象
-
hash:
true - 收集出来的是一个 JS 对象结构false - 收集出来的是一个查询字符串格式
-
empty:
true - 收集空值false - 不收集空值
-
-
上传图片
如果有上传文件需要,请求的类型必须是multipart/form-data
- 获取图片文件对象
- 使用FormData携带图片文件
1
2const formData = new FormData();
formData.append('image', imageFile); - 提交表单数据到服务器,使用图片url网址
AJAX原理
XMLHttpRequest(XHR)对象,该对象用于与服务器交互,通过XHR可以在不刷新页面的情况下请求特定URL获取数据,XHR在AJAX中被大量使用
XMLHttpRequest
- 使用XMLHttpRequest携带查询参数:
- 创建XMLHttpRequest对象
const xhr=new XMLHttpRequest
- 使用open方法配置请求方法和请求url地址(如果是get,需要在url后面携带查询参数字符串)
xhr.open('method','url')
- 如果多个参数配置不便,可以使用内置对象
URLSearchParams
对象将参数转成"参数名=值&参数名=值"的形式,接着再拼接只需要先将该对象转换成字符串再拼接到url的问号后即可
1
2
3
4
5
6
7
8
9// 1. 创建 URLSearchParams 对象
const paramsObj = new URLSearchParams({
参数名1: 值1,
参数名2: 值2
})
// 2. 生成指定格式查询参数字符串
const queryString = paramsObj.toString()
// 结果:参数名1=值1&参数名2=值2 - 如果多个参数配置不便,可以使用内置对象
- 监听loadend事件,接受响应结果
- 监听:
xhr.addEventListener('loadend',()=>{})
- 响应结果
xhr.response
(注意,但会的数据结果是JSON字符串而不是对象,因此需要将其转换成对象)
- 监听:
- 发起请求:需要调用
xhr.send()
方法发起请求
- 创建XMLHttpRequest对象
- 使用XMLHttpRequest携带请求体数据:
- 新建XMLHttpRequest对象
- 调用open方法
- 检测loadend事件
- 设置请求头:
xhr.setRequestHeader('Content-Type', 'application/json')
,在请求头中设置Content-Type:application/json
- 准备要提交的数据,将其转换为JSON字符串
JSON.stringify(userObj)
- 发送请求体数据,注意要在其中携带数据
xhr.send(userStr)
Promise
Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值;对于成功或失败Promise都会关联后续的处理函数
- Promise语法
1 |
|
- 一些注意:
- then函数的格式如下
p.then(函数1[,函数2])
,第一个参数是resolved状态的回调函数。第二个参数是rejected状态的回调函数。第二个参数可选,第一个参数必写 - Promise.prototype.catch 是 Promise.prototype.then(null, reject)的别名,用于指定当promise对象的状态从pending变成rejected的回调函数 。
- then函数的格式如下
-
Promise的三种状态
- 待定状态 pending :初始状态,既没有被兑现,也没有被拒绝
- 已兑现 fulfilled:操作成功完成 导致then的函数被触发
- 已拒绝 rejected:操作失败 导致reject的函数被触发
- 注意:Promise对象一旦被兑现/拒绝,就无法再被改变
- AJAX如何判断是否请求响应成功了?响应状态码在大于等于 200 并且小于 300 的范围是成功的
1
2
3
4
5if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
} -
模拟封装简易axois
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
31
32
33
34
35
36
37
38
39
40
41
42//函数
function myAxois(config){
return new Promise((resolve,reject) =>{
const xhr = new XMLHttpRequest()
if (config.params) {
// 使用URLSearchParams转换,并携带到url上
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
// 把查询参数字符串,拼接在url?后面
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
// 3. 调用成功/失败的处理程序
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
// 1. 判断有data选项,携带请求体
if (config.data) {
// 2. 转换数据类型,在send中发送
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
// 如果没有请求体数据,正常的发起请求
xhr.send()
}
})
}
//使用函数
myAxios({
url: 'http://hmajax.itheima.net/api/province'
}).then(result => {
console.log(result)
document.querySelector('.my-p').innerHTML = result.list.join('<br>')
}).catch(error => {
console.log(error)
document.querySelector('.my-p').innerHTML = error.message
})
AJAX进阶
同步代码和异步代码
同步代码:逐行执行,需原地等待结果后,才继续向下执行
异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发回调函数传递结果
异步代码:setTimeout/setInterval;事件;AJAX
回调函数地狱
概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱
缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身
1 |
|
Promise链式调用
参考1
参考2
使用then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束;通过链式调用可以解决回调函数嵌套的问题
如果 .then
(或 catch/finally
都可以)处理程序(handler)返回一个 promise,那么链的其余部分将会等待,直到它(返回的promise)状态变为 settled。当它被 settled 后,其 result(或 error)将被进一步传递下去。
示例:
1 |
|
解决回调地狱:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来
1 |
|
ascyn和await
async函数是使用async关键字声明的函数,使用async声明的函数中允许使用await关键字。这两个关键字可以让我们用一种更为简洁的方式写出基于Promise的异步行为,无需可以地链式调用promise
使用async和await解决回调函数地狱
1 |
|
错误捕捉
使用try...catch
语句块
1 |
|
事件循环
看JS的笔记,相关内容已补充
宏任务与微任务
ES6之后,JS引入了Promise对象,让JS引擎也可以发起异步任务
-
异步任务分为:
- 宏任务:由浏览器环境执行的异步代码
- JS脚本执行事件(script),setTimeout/setInterval,AJAX请求完成事件,用户交互事件
- 微任务:由JS引擎环境执行的异步代码
- Promise对象.then()【promise本身是同步的,then和catch回调函数是异步的】
- 宏任务:由浏览器环境执行的异步代码
-
宏任务、微任务和事件循环
- 【遇到第一个script脚本事件宏任务】先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
- 更详细地讲【严谨区分宏任务和微任务之间的关系】:实际上是先执行同步任务,异步任务有宏任务和微任务两种,先将宏任务添加到宏任务队列中,将宏任务里面的微任务添加到微任务队列中。所有同步执行完之后执行异步,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行。之后就一直循环…参考
注意:宏任务每次在执行同步代码时,产生微任务队列,清空微任务队列任务后,微任务队列空间释放!
下一次宏任务执行时,遇到微任务代码,才会再次申请微任务队列空间放入回调函数消息排队
总结:一个宏任务包含微任务队列,他们之间是包含关系,不是并列关系 -
事件循环练习题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19console.log(1)
//代码1
setTimeout(() => {
console.log(2)
const p = new Promise(resolve => resolve(3))
p.then(result => console.log(result))
}, 0)
//代码2
const p = new Promise(resolve => {
setTimeout(() => {
console.log(4)
}, 0)
resolve(5)
})
p.then(result => console.log(result))
//代码3
const p2 = new Promise(resolve => resolve(6))
p2.then(result => console.log(result))
console.log(7)- 分析:
- 首先执行console.log(1)
- 接着把代码1 setTimeout放到浏览器环境,0秒立即执行完毕,回调函数放到宏队列中【宏队列:代码1回调函数】
- 执行代码2 promise放到栈中执行,代码2中的计时函数放到浏览器环境,秒执行完毕,把回调函数放到宏队列【宏队列:代码1回调函数,代码2回调函数】;p返回,then函数放到微队列中【微队列:代码2的then函数】
- 执行代码3 promise直接返回,【微队列:代码2的then函数;代码3的then函数】
- console.log(7)
- 微队列:代码2的then函数:resolve(5) 打印5
- 微队列:代码3的then函数:resolve(6) 打印6
- 宏队列:代码1回调函数:console.log(2) 打印2 接着promise 【微队列 代码1的then】
- 微队列:代码1的then resolve(3)打印3
- 宏队列:代码2回调函数 console.log(4)打印4
- 最终结果:1 7 5 6 2 3 4
- 分析:
Promise.all静态方法
合并多个 Promise 对象,等待所有同时成功完成(或某一个失败),做后续逻辑
基本语法:
1 |
|
与axios结合:
1 |
|
Node.js
Node.js是一个跨平台的JS运行环境,使开发者可以搭建服务端的JS应用程序
Node.js 是一个独立的 JavaScript 运行环境,能独立执行 JS 代码,因为这个特点,它可以用来编写服务器后端的应用程序
Node.js 作用除了编写后端应用程序,也可以对前端代码进行压缩,转译,整合等等,提高前端开发和运行效率
Node.js 基于Chrome V8 引擎封装,独立执行 JS 代码,但是语法和浏览器环境的 V8 有所不同,没有 document 和 window (BOM和DOM)但是都支持 ECMAScript 标准的代码语法
- Nodejs使用:例如:新建
test.js
文件后,使用node test.js
即使用js文件的相对路径就可以直接运行目标js文件
node模块
模块:类似插件,封装了方法和属性供我们使用
模块的使用方式:
- 加载模块:
const fs = require('fs')
- 使用模块:
fs.write()
- fs 模块:封装了与本机文件系统进行交互的,方法和属性
- path模块:Nodejs的代码中,相对路径是根据终端所在路径来查找的,建议在Nodejs代码中,使用绝对路径
- 绝对路径的使用:使用模块内置变量
__dirname
配合path.join()
来得到绝对路径使用;__dirname
会获取从根路径到当前文件的父级目录,join方法会将分隔符自动处理,因此一般使用只需要path.join(__dirname,'相对路径')即可
- 绝对路径的使用:使用模块内置变量
- node的使用场景:代码压缩
功能
中后台系统开发
前端常用中间件
- 数据存储类:redis mysql
- 配置管理类:qconfig
- 消息队列类:qmq kalka
- 监控告警类:metric cat
- 日志类:clog
注意:中间件在服务端运行,部分中间件如果想在客户端运行,需要包装成一个http服务
关于Antd
- 在中后台视觉体系中的布局系统,有以下几个方向需要关注:
- 统一的画板尺寸(antd以1440作为画板尺寸)
- 适配方案:左右布局与上下布局
- 栅格系统:24栅格体系
- 布局layout
flex布局参考:http://c.biancheng.net/css3/flex.html