前端其它

AJAX

AJAX(Asynchronous JavaScript And XML )是一种使用 XMLHttpRequest 技术构建更复杂,动态的网页的编程实践。(来自mdn)

axios使用

1
2
3
4
5
6
7
8
axios({
url: '目标资源地址',
params:{
key:value
}
}).then((result) => {
// 对服务器返回的数据做后续处理
})

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
2
3
4
5
6
7
8
9
axios({
url: '目标资源地址',
method: '请求方法',
data: {
kay: value
}
}).then(result => {
// 对服务器返回的数据做后续处理
})

错误处理

只要在之后的函数中添加catch即可

1
2
3
4
5
6
7
axios({
// ...请求选项
}).then(result => {
// 处理成功数据
}).catch(error => {
// 处理失败错误
})

请求报文

请求报文:浏览器按照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

  1. 获取图片文件对象
  2. 使用FormData携带图片文件
    1
    2
    const formData = new FormData();
    formData.append('image', imageFile);
  3. 提交表单数据到服务器,使用图片url网址

AJAX原理

XMLHttpRequest(XHR)对象,该对象用于与服务器交互,通过XHR可以在不刷新页面的情况下请求特定URL获取数据,XHR在AJAX中被大量使用

XMLHttpRequest

  • 使用XMLHttpRequest携带查询参数:
    1. 创建XMLHttpRequest对象const xhr=new XMLHttpRequest
    2. 使用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
    3. 监听loadend事件,接受响应结果
      • 监听:xhr.addEventListener('loadend',()=>{})
      • 响应结果xhr.response(注意,但会的数据结果是JSON字符串而不是对象,因此需要将其转换成对象)
    4. 发起请求:需要调用xhr.send()方法发起请求
  • 使用XMLHttpRequest携带请求体数据:
    1. 新建XMLHttpRequest对象
    2. 调用open方法
    3. 检测loadend事件
    4. 设置请求头:xhr.setRequestHeader('Content-Type', 'application/json'),在请求头中设置Content-Type:application/json
    5. 准备要提交的数据,将其转换为JSON字符串JSON.stringify(userObj)
    6. 发送请求体数据,注意要在其中携带数据xhr.send(userStr)

Promise

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值;对于成功或失败Promise都会关联后续的处理函数

  1. Promise语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//创建Promise对象
const p = new Promise((resolve,reject)=>{
// 执行异步任务-并传递结果
// 成功调用: resolve(值) 触发 then() 执行
resolve(value);//value会成为then中的处理函数的参数
reject(value);//类似,vlaue会成为catch中处理函数的参数
// 失败调用: reject(值) 触发 catch() 执行
})
//接收结果
p.then(result =>{

}).catch(error =>{

})
  • 一些注意:
    • then函数的格式如下p.then(函数1[,函数2]),第一个参数是resolved状态的回调函数。第二个参数是rejected状态的回调函数。第二个参数可选,第一个参数必写
    • Promise.prototype.catch 是 Promise.prototype.then(null, reject)的别名,用于指定当promise对象的状态从pending变成rejected的回调函数 。​​​​​​​
  1. Promise的三种状态

    • 待定状态 pending :初始状态,既没有被兑现,也没有被拒绝
    • 已兑现 fulfilled:操作成功完成 导致then的函数被触发
    • 已拒绝 rejected:操作失败 导致reject的函数被触发
    • 注意:Promise对象一旦被兑现/拒绝,就无法再被改变
    • AJAX如何判断是否请求响应成功了?响应状态码在大于等于 200 并且小于 300 的范围是成功的
    1
    2
    3
    4
    5
    if (xhr.status >= 200 && xhr.status < 300) {
    resolve(JSON.parse(xhr.response))
    } else {
    reject(new Error(xhr.response))
    }
  2. 模拟封装简易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
2
3
4
5
6
7
8
9
10
11
12
13
axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
const pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 获取第一个省份默认下属的第一个城市名字
axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } }).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 获取第一个城市默认下属第一个地区名字
axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } }).then(result => {
document.querySelector('.area').innerHTML = result.data.list[0]
})
})
})

Promise链式调用

参考1
参考2
使用then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束;通过链式调用可以解决回调函数嵌套的问题

如果 .then(或 catch/finally 都可以)处理程序(handler)返回一个 promise,那么链的其余部分将会等待,直到(返回的promise)状态变为 settled。当它被 settled 后,其 result(或 error)将被进一步传递下去。

示例:

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
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('北京市')
}, 2000)
})

// 2. 获取省份名字
//这个p2是p.then创造的promise对象
const p2 = p.then(result => {
console.log(result)
// 3. 创建Promise对象-模拟请求城市名字
// return Promise对象最终状态和结果,影响到新的Promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + '--- 北京')
}, 2000)
})
})

// 4. 获取城市名字
p2.then(result => {
console.log(result)
})

// then()原地的结果是一个新的Promise对象
console.log(p2 === p)

解决回调地狱:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let pname = ''
// 1. 得到-获取省份Promise对象
axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {
pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 2. 得到-获取城市Promise对象
return axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})
}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 3. 得到-获取地区Promise对象
return axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
}).then(result => {
console.log(result)
const areaName = result.data.list[0]
document.querySelector('.area').innerHTML = areaName
})

ascyn和await

async函数是使用async关键字声明的函数,使用async声明的函数中允许使用await关键字。这两个关键字可以让我们用一种更为简洁的方式写出基于Promise的异步行为,无需可以地链式调用promise

使用async和await解决回调函数地狱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
async function getData() {
try{
// 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
} catch(error){
console.dir(error)
}

}

错误捕捉

使用try...catch语句块

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

事件循环

看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
    19
    console.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
2
3
4
5
6
const p = Promise.all([Promise对象, Promise对象, ...])
p.then(result => {
// result 结果: [Promise对象成功结果, Promise对象成功结果, ...]
}).catch(error => {
// 第一个失败的 Promise 对象,抛出的异常对象
})

与axios结合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 1. 请求城市天气,得到Promise对象
const bjPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '110100' } })
const shPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '310100' } })
const gzPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440100' } })
const szPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440300' } })

// 2. 使用Promise.all,合并多个Promise对象
const p = Promise.all([bjPromise, shPromise, gzPromise, szPromise])
p.then(result => {
// 注意:结果数组顺序和合并时顺序是一致
console.log(result)
const htmlStr = result.map(item => {
return `<li>${item.data.data.area} --- ${item.data.data.weather}</li>`
}).join('')
document.querySelector('.my-ul').innerHTML = htmlStr
}).catch(error => {
console.dir(error)
})

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模块

模块:类似插件,封装了方法和属性供我们使用

模块的使用方式:

  1. 加载模块:const fs = require('fs')
  2. 使用模块:fs.write()
  • fs 模块:封装了与本机文件系统进行交互的,方法和属性
  • path模块:Nodejs的代码中,相对路径是根据终端所在路径来查找的,建议在Nodejs代码中,使用绝对路径
    • 绝对路径的使用:使用模块内置变量 __dirname配合 path.join() 来得到绝对路径使用;__dirname会获取从根路径到当前文件的父级目录,join方法会将分隔符自动处理,因此一般使用只需要 path.join(__dirname,'相对路径')即可
  • node的使用场景:代码压缩

功能

中后台系统开发

前端常用中间件

  1. 数据存储类:redis mysql
  2. 配置管理类:qconfig
  3. 消息队列类:qmq kalka
  4. 监控告警类:metric cat
  5. 日志类:clog
    注意:中间件在服务端运行,部分中间件如果想在客户端运行,需要包装成一个http服务

关于Antd

  • 在中后台视觉体系中的布局系统,有以下几个方向需要关注:
    1. 统一的画板尺寸(antd以1440作为画板尺寸)
    2. 适配方案:左右布局与上下布局
    3. 栅格系统:24栅格体系
    4. 布局layout
      flex布局参考:http://c.biancheng.net/css3/flex.html

前端其它
https://mapllle.site/2024/02/27/frontend/Others/
作者
MAple
发布于
2024年2月27日
许可协议