AJAX学习 ---- axios体验

前言:AJAX是浏览器和服务器进行数据通信的技术

一、先使用 axios 第三方库,与服务器数据进行数据通信

为什么要使用该第三方库,不直接使用底层原理进行呢?
  • 基于XMLHttpRequest封装、代码简单、月下载量在14亿次
  • Vue、react项目中都会用到axios
axios是怎么进行操作的呢?

axios作为第三方库,在使用时需要将该库相关的 js 代码引入到自身网页中,然后会得到一个全局的 axios函数,那么就能调用该函数了。(注意:① axios函数中传入配置对象 ② 用 .then回调函数接收结果,并做后续处理)

1.axios使用:

需求:请求目标资源地址,拿到省份列表数据,显示到页面
目标资源地址:http://hmajax.itheima.net/api/province

可以看到浏览器中直接访问返回的是对象结构的 json 字符串,在该对象中有两组 key和value,一对是message,一对是list

补充:之所以是 axios({ })这样子的形式,是因为 axios 是一个函数,函数调用的方式就是 函数(参数1,参数2, ...)而之所以这个里边还有花括号,是因为传入的是一个对象,所以用花括号将对象括起来

接下来从 result 对象中拿到省份列表数据

  • 第一次打印出整个result对象
  • 第二次打印出省份列表
  • 第三次数组中用 <br> 作为分隔符将所有元素合并成一个字符串
  • 把合成的字符串设置到HTML元素的 innerHTML中,浏览器会把它当作HTML标签进行解析,<br>真的会换行
2、认识URL

定义:统一资源定位符,俗称网页地址,简称网址,用于访问网络上的资源。

https://www.baidu.con/index.html,该地址定位到的是网页资源。

https://www.itheima.com/images/logo.png ,图片资源

http://hmajax.itheima.net/api/province ,数据资源

http://hmajax.itheima.net/api/province

组成:

http:// 协议

hmajax.itheima.net 域名

/api/province 资源路径

①http协议:超文本传输协议,规定浏览器和服务器之间传输数据的格式

②域名:标记要访问的服务器在互联网中方位。例如 baidu.com就是百度服务器

③资源路径:标记资源在服务器下的具体位置

获取 - 新闻列表

需求:使用axios从服务器拿到新闻列表数据

目标资源地址:http://hmajax.itheima.net/api/news

在此之前已经学习了引入 axios 第三方库进行获取 服务器数据,现在用来获取新闻数据也是一样的使用方法

补充:

axios( )是调用函数axios,那么axios( ).then( )是不是就说明 then是axios函数的方法呢?

答:不是,then是 promise 对象的方法,况且 只有对象里边才能包含方法,方法就是函数,函数里边怎么能包含函数呢。

promise是 javascript中用于处理异步操作的一个 内置对象,它提供了两个重要方法。

.then(onFulfilled, onRejected?) 当 Promise 成功时(fulfilled),执行 onFulfilled函数,你在这里处理返回的数据

.catch(onRejected) 当 Promise 失败时(rejected),执行这个函数,你在这里处理错误

javascript 复制代码
// 1. axios(...) 是函数调用,返回一个 Promise
const promise = axios({
  method: 'get',
  url: '/api/data'
});

// 2. then 是 promise 对象的方法
promise.then(function (response) {
  console.log('请求成功', response.data);
}).catch(function (error) {
  console.error('请求失败', error);
});




//或简写为一行链式调用
axios({
  method: 'get',
  url: '/api/data'
}).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});
3、URL查询参数

定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据

语法:http://xxxx.com/xxx/xxx?参数名1=值1 & 参数名2 = 值2(URL之后用 ?引出特定的参数,多个参数时 用 & 进行连接)

axios - 查询参数

语法: 使用 axios 提供的 params 选项

注意:axios在运行时把参数名和值,拼接到 url?参数名= 值

城市列表:http://hmajax.itheima.net/api/city?pname=河北省

javascript 复制代码
      axios({
        url:'目标资源地址',
        params:{
          参数名:值
        }
      }).then(result => {
        //对服务器返回的数据做后续处理
      })

打印出了 axios 的结果对象,同样是在 data 属性中看到了后端给出的 河北省 对应城市列表:

如果想要将该城市呈现在页面中,那么就需要一个容器,也就是html标签,获取该标签之后将内容插入到标签中。同样,需要将数组转换成字符串,使用 join方法,并且使用 <br> 标签作为分隔符,在插入时使用 innerHTML 进行插入时识别 标签,继而进行换行

地区查询
需求:根据树入的省份名字和城市名字,查询地区并渲染列表

首先:确定URL网址和参数说明

  • 查询某个省内某个城市的所有地区:http://hmajax.itheima.net/api/area
  • 参数:
    pname:省份名字或直辖市名字,比如北京、福建省、辽宁省...
    cname:城市名字,比如北京市、厦门市、大连市...

主体大概框架:一个大的 div 容器 。然后是一个form标签包含两个并列同类 mb-3 col 的 div容器,这两个标签中都包含类为 form-label的 label 标注标签以及 input树入框获取输入的数据。与form表单并列的是button 按钮。接着是 li 无序列表。

补充:input输入框中属性作用 , value :还未输入时默认值(预填入),name:是该输入框的一个名称标识,用于在提交表单时告诉服务器 "这个输入框的值,对应的是名为 city 的字段"

给按钮添加点击事件,点击之后获取输入框中输入的省份和城市名字,基于axios 将输入框中的省份和城市传到服务器上,然后把服务器返回的省份城市列表数据用 map 遍历,给每个把每个数据都添加到 li 标签中。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>地区查询</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
  <style>
    :root {
       font-size:15px;
    }
    body {
      padding-top:15px;
    }

  </style>
</head>
<body>
  <div class="container">
    <form class="row" id="editForm">
      <!-- 输入省份名字 -->
       <div class="mb-3 col">
        <label class="form-label">省份名字</label>
        <input type="text" value="北京" name="province" class="form-control province" placeholder="请树入省份名称">
       </div>
       <!-- 输入城市名字 -->
        <div class="mb-3 col">
          <label class="form-label">名字城市</label>
          <input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名字">
        </div>
    </form>
    <button type="button" class="btn btn-primary sel-btn">查询</button>
    <br>
    <p>地区列表:</p>
    <ul class="list-group">
      <li class="list-group-item">东城区</li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
        /*
      获取地区列表: http://hmajax.itheima.net/api/area
      查询参数:
        pname: 省份或直辖市名字
        cname: 城市名字
    */
     // 目标: 根据省份和城市名字, 查询地区列表
     // 1. 查询按钮-点击事件
     document.querySelector('.sel-btn').addEventListener('click',() => {
      //2.获取省份和城市名字
      let pname = document.querySelector('.province').value
      let cname = document.querySelector('.city').value
      //3.基于axios请求地区列表数据
      axios({
        url:'http://hmajax.itheima.net/api/area',
        params:{
          pname,
          cname
        }
      }).then(result => {
        //4.把数据转li标签插入到页面上
        let list = result.data.list
        console.log(list)
        //遍历数组中每个元素,这里用areaName表示每个元素,将每个元素包含在li标签中
        let theLi = list.map(areaName => `<li class="list-group-item">${areaName}</li>`).join('')
        console.log(theLi)
        //innerHTML能直接识别标签,在网页中显示出小圆点
        document.querySelector('.list-group').innerHTML = theLi
      })
     })
  </script>

  
</body>
</html>

补充:里边的 axios 请求,用params写查询参数时,格式应当是 属性名:变量名,但是这里的属性名和变量名相同了,所以只用写一个就行。(今后的变量名可尽量写跟后端给出的属性名一样,那样就只用写出一个了)

下面查询了北京的地区列表:

4.常用请求方法

请求方法:对服务器资源,要执行的操作

请求方法 操作
GET 获取数据
POST 提交数据
PUT 修改数据(全部)
DELETE 删除数据
PATCH 修改数据(部分)

① 什么时候会使用到 提交数据 这种场景呢?

  • 想在手机和电脑上浏览同一份订单数据,那这份订单数据应该保存在服务器上。
  • 注册了一个百度账号,手机端和电脑端也想要去登录该账号,账号信息也该保存在服务器上

总结:数据提交的场景 ------ 当数据需要在服务器上保存的时候

② 如何将数据提交到 服务器上呢?

axios请求配置: (在原来仅有的URL属性之外加上了 method 和 data 两个配置项)

url : 请求的URL网址

method:请求的方法,GET 可省略不写(不区分大小写)

data:提交数据(data:{ 参数名:参数值 })

(如果是要请求数据,那么就是params:{ 参数名:参数值 })

③ 案例-数据提交 - 注册账号

需求:通过 axios 提交用户名和密码,完成注册功能

注册用户URL地址:http://hmajax.itheima.net/api/register

请求方法:POST

参数名:

username 用户名(中英文和数字组成,最少8位)

password 密码(最少6位)

④点击注册用户之后,控制台就会返回注册结果,显示已经注册成功了。

注意:不能跟视频中注册的用户名一样,否则报错,自己换一个用户名就行

由此衍生出一计:运用已经注册过的用户名再注册一次,如果报错,那么就说明已经注册成功了。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>请求方法-数据提交</title>
</head>
<body>
  <button class="btn">注册用户</button>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /*
    注册用户:http://hmajax.itheima.net/api/register
    请求方法:POST
    参数名:
      username:用户名(中英文组成,最少8位)
      password:密码(最少6位)
    目标:点击按钮,通过axios提交用户和密码,完成注册
      */
      document.querySelector('.btn').addEventListener('click',() => {
        axios({
          url:"http://hmajax.itheima.net/api/register",
          //指定请求方法
          method:'post',
          //提交数据
          data:{
            username:'ithaima789',
            password:'123456'
          }
        }).then(result => {
          console.log(result)
        })
      })
  </script>
  
</body>
</html>
5.axios错误处理

场景:再次注册相同的账号,会遇到报错信息

处理:用更直观的方式,给普通用户·展示错误信息(例如弹框)

语法:在 then 方法后面,通过点语法调用catch方法,传入回调函数并定义形参

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>axios错误处理</title>
</head>
<body>
  <button class="btn">注册用户</button>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /*
    注册用户:http://hmajax.itheima.net/api/register
    请求方法:POST
    参数名:
      username:用户名(中英文组成,最少8位)
      password:密码(最少6位)
    目标:点击按钮,通过axios提交用户和密码,完成注册
    需求:使用axios错误处理语法,拿到报错信息,弹框反馈给用户
      */
      document.querySelector('.btn').addEventListener('click',() => {
        axios({
          url:"http://hmajax.itheima.net/api/register",
          //指定请求方法
          method:'post',
          //提交数据
          data:{
            username:'ithaima789',
            password:'123456'
          }
        }).then(result => {
          console.log(result)
          //catch方法拿到错误,还要传入一个回调函数
        }).catch(error => {
          //处理错误信息
          console.log(error)
          //把真正错误原因取出来
          console.log(error.response.data.message)
          alert(error.response.data.message)
        })
      })

  </script>
  
</body>
</html>

axios中,如果成功了,那么就会调用 then的回调函数执行;失败则会调用 catch 的回调函数执行

6. HTTP协议 - 请求报文

①HTTP协议:规定了浏览器发送及服务器返回内容的格式

②请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容

③请求报文组成部分:

|-------|-------------------------------|
| 1.请求行 | 请求方法,URL,协议 |
| 2.请求头 | 以键值对的格式携带的附加信息,比如Content-Type |
| 3.空行 | 分隔请求头,空行之后的是发送给服务器的资源 |
| 4.请求体 | 发送的资源 |

查看请求报文 :网络 --> Fetch / XHR --> 标头 / 负载

请求行、请求头:在标头中的请求标头可以看(而之所以不是 json 格式是因为浏览器将之格式化了,点击旁边原始则能看到 json 格式)

请求体(发送的资源)可以在 "负载" 中查看,同样点击 "原始"就能看到原始 json 请求体,也就是 data 中发送的数据

7.请求报文 - 错误排查

需求:通过请求报文排查错误原因,并修复

现情况:输入正确用户名和密码无法登录

  • 用户名: itheima007
  • 密码:7654321
  • 在网页中输入用户名和密码发现登陆出错,不能登录
  • 打开开发者工具,将源码中 input 输入框中 密码框类型 type 设置为 text 可见,确保密码没有输入错误
  • 返回代码中 axios 里边携带的 用户名和密码 没有 出错,接着一步步往上定位到 用户名和密码的 定义,最终是发现了 密码定义 时获取的是用户名输入框 的内容。最终排除错误。
8.响应报文

HTTP协议:规定了浏览器发送及服务器返回内容的格式

响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容

|------------|-------------------------------|
| 1.响应行(状态行) | 协议、HTTP响应状态码、状态信息 |
| 2.响应头 | 以键值对的格式携带的附加信息,比如Content-Type |
| 3.空行 | 分隔响应头,空行之后是服务器返回的资源 |
| 4.响应体 | 返回的资源 |

①HTTP响应状态码:用来表明请求是否成功完成

404 :服务器找不到资源

|---------|-----------|
| 状态码 | 说明 |
| 1xx | 信息 |
| 2xx | 成功 |
| 3xx | 重定向消息 |
| 4xx | 客户端错误 |
| 5xx | 服务端错误 |

②查看响应报文(在"响应标头"当中或"响应" 中)

  • 当 故意把 URL 写错,然后就 能得到 404 状态码(服务器找不到资源),以及Not Found状态信息:未找到。

  • 如果是输入的 用户名 或密码错误,那么响应标头返回的状态信息就会 是 request

  • 如果成功的话,那么返回状态信息 OK

    补充:"响应" 中的信息有 :

  • code:后端定义的业务状态码。
    10006:密码错误
    10001:用户找不到
    10004:用户没登陆或token过期
    99999:后端自定义的系统异常
    0 / 200:请求成功

  • message:表示请求的处理结果(直接中文表示,例"用户名或密码输入错误")

  • data:请求中,发送的数据,后端返回的核心数据部分

"响应"中查看返回的 资源体

9.接口文档

定义:描述接口的文章(后端工程师)

接口:使用AJAX和服务器通讯时 ,使用URL,请求方法,以及参数

例如该接口(重点详介绍查询参数):

  • 参数名 pname ,位置是 query ,意思是查询,那么我就能知道它是查询参数,所以就知道了在 axios 发送请求时 ,pname要写在 params 配置项中
  • 如果请求参数是 body 参数,那么就是请求体参数,在 axios 发送时,要写在 data 配置项中

AJAX该部分的接口文档:欢迎使用 - B站-AJAX和黑马头条-数据管理平台

①编写登录页代码:
  • 一个登录按钮,一个用户名、密码输入框(input中id属性值和label中for属性值一样,当),当点击label标签中的文字时,浏览器会自动把光标聚焦到输入框中
  • 获取用户名输入框、密码输入框中的 value 值赋值给变量,给按钮添加点击事件,点击即发送请求,请求时将 参数传入
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>接口文档</title>
</head>
<body>
  <button class="btn">登录</button>
  <br>
  <label for="us">用户名</label>
  <input type="text" value="小明" id="us" class="username" placeholder="输入用户名" name="username" required>
  <br>
  <label for="pa">密码</label>
  <input type="password" value="1234567" id="pa" class="password" placeholder="输入密码" name="password" disabled>
  
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    //用户注册
    const username = document.querySelector('.username').value
    const password = document.querySelector('.password').value
    document.querySelector('.btn').addEventListener('click',() => {
      axios({
        url:"http://hmajax.itheima.net/api/login",
        method:"post",
        data:{
          username:'itheima007',
          password:'7654321'
        }
      }).then(result => {
        alert('注册成功')
      }).catch(reason => {
        alert('注册失败')
      })
    })

  </script>
 
</body>
</html>
② 案例 - 用户登录
  1. 点击登录时,判断用户名和密码长度
  2. 提交数据和服务器通信
  3. 提示信息(成功是绿色提示框,失败是红色提示框)

注意:在成功时需要提示框,失败时需要提示框,密码和用户名长度不符合规范时需要提示框,都是一样的逻辑,所以直接将之封装为函数

html 复制代码
<!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>案例_登录</title>
  <!-- 引入bootstrap.css -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
  <!-- 公共 -->
  <style>
    html,
    body {
      background-color: #EDF0F5;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .container {
      width: 520px;
      height: 540px;
      background-color: #fff;
      padding: 60px;
      box-sizing: border-box;
    }

    .container h3 {
      font-weight: 900;
    }
  </style>
  <!-- 表单容器和内容 -->
  <style>
    .form_wrap {
      color: #8B929D !important;
    }

    .form-text {
      color: #8B929D !important;
    }
  </style>
  <!-- 提示框样式 -->
  <style>
    .alert {
      transition: .5s;
      opacity: 0;
    }

    .alert.show {
      opacity: 1;
    }
  </style>
</head>

<body>
  <div class="container">
    <h3>欢迎-登录</h3>
    <!-- 登录结果-提示框 -->
    <div class="alert alert-success" role="alert">
      提示消息
    </div>
    <!-- 表单 -->
    <div class="form_wrap">
      <form>
        <div class="mb-3">
          <label for="username" class="form-label">账号名</label>
          <input type="text" class="form-control username">
        </div>
        <div class="mb-3">
          <label for="password" class="form-label">密码</label>
          <input type="password" class="form-control password">
        </div>
        <button type="button" class="btn btn-primary btn-login"> 登 录 </button>
      </form>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    // 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
    // 目标2.使用提示框,反馈提示信息
    // 2.1 获取提示框
    const myAlert = document.querySelector('.alert')
    //2.2 封装提示函数,重复调用,满足提示需求
    // 功能 :
    // 1.显示提示框
    // 2.不同提示文字msg,成功绿色,失败红色isSuccess(true成功,false失败)
    // 3.过2 秒后,让提示框自动消失
    function alertFn(msg,isSuccess) {
      //1.显示提示框 
      myAlert.classList.add('show')

      //2.实现细节(给提示框中放入消息)
      myAlert.innerText = msg
      //给框设置背景色,如果外边传进来是 true ,那么就给出一个成功类名,否则是失败类名
      const bgStyle = isSuccess ? 'alert-success':'alert-danger'
      //确认类名之后将其添加到提示框中
      myAlert.classList.add(bgStyle)

      //3. 过2秒隐藏
      setTimeout(() => {
        myAlert.classList.remove('show')
        //提示:避免类名冲突,重置背景色,也就是文字和背景色要一同消失
        myAlert.classList.remove(bgStyle)
      },2000)

    }
    
    // 1.1 登录-点击事件
    document.querySelector('.btn-login').addEventListener('click', () => {
      // 1.2 获取用户名和密码
      const username = document.querySelector('.username').value
      const password = document.querySelector('.password').value
      // console.log(username, password)

      // 1.3 判断长度
      if (username.length < 8) {
        alertFn('用户名必须大于8位',false)
        return // 阻止代码继续执行
      }
      if (password.length < 6) {
        alertFn('密码必须大于等于6位',false)
        return // 阻止代码继续执行
      }

      // 1.4 基于axios提交用户名和密码
      // console.log('提交数据到服务器')
      axios({
        url: 'http://hmajax.itheima.net/api/login',
        method: 'POST',
        data: {
          username,
          password
        }
      }).then(result => {
        console.log(result)
        //想在表面展现后端给出的message提示信息,直接右键复制路径
        alertFn(result.data.message,true)
      }).catch(error => {
        console.log(error)
        alertFn(error.data.message,false)
      })
    })
  </script>
</body>

</html>

逐个拆解需求:

点击登录时,判断用户名和密码长度:

为按钮注册点击事件,点击之后获取输入框中输入的用户名和密码,简单进行用户名和密码的长度判断(长度不符合,用 return 组织代码继续进行)

其实这里仅仅是对输入内容进行前端简单校验,还未涉及到与后端交互是否与注册的用户名和密码一致

提交数据和服务器通信

axios发送请求,经典 url,method,data,并且用于捕获成功的 then 方法,以及捕获失败的 catch 方法

提示信息

在判断用户名长度、密码长度、登陆成功、登陆失败,这四种情况都必须使用提示框进行提示,因为情况都一样,所以选择封装函数进行重复调用。

  1. 首先获取提示框,在html中提示框仅用 div来进行简单表示
  2. 接着将传入的信息覆盖原信息.如果是判断长度部分,那么调用函数时,传入的形参msg就是我们 aler 出来的 "密码不能小于8位"这样的字符串;如果是关于登录成功与否的信息,那么就需要从then或catch中捕获的对象中找(简而言之,就是判断长度的msg仍然是自己写出的对象,而是否登陆成功的msg是要到控制台的对象.data.message中)

注意:class类中,当有多个类型时,后边的类值会把前边的类值覆盖掉,所以这里才会有最后要把背景色给移除

直接浏览器中搜索 Alert 能知 该提示框表示成功和失败时的代码如何

10.form-serialize 插件

作用:快速收集表单元素的值(现在好像不用这个了,用FornData API)

语法:

  • 首先进行引入
  • 然后使用 serialize 函数,其中第一个参数是获取的哪一个表单元素的表单的值,第二个参数是一个配置对象(实际开发中只需要 hash 和 empty 即可)
  1. 引入 该插件,插件文件在 lib 文件夹中

  2. 获取表单将之作为 serialize 的第一个参数,第二个参数是个配置对象,其中 hash 为true就会获取到的是 json 对象,否则是查询字符串 ,例如 ** = xx; empty为 true 表示输入框为空时,在获取的时候也要把 空值获取出来。

    简言 ,serialize函数用来获取输入框中输入的内容,并且输入框 input 中的 name的值会作为 控制台获取时 的 key,而输入的内容就作为 value(name值作为对象属性名)

hash和empty都 为 true

hash改为false,而empty不变

可见获取到的值已经是查询字符串形式了

hash为true,而empty为 false

可见如果输入为空那么就不会获取空值

①使用 form-serialize 插件,收集用户名和密码,完善登录案例
  • 获取 form 元素作为 serialize 函数的第一个参数
  • 解构将旧的变量名的值赋值给新的变量名,虽然关乎旧的变量值,但是只出现了新旧变量名。
相关推荐
24zhgjx-fuhao3 小时前
HTTP的配置
网络·网络协议·http
Man3 小时前
当我们执行 npm run xxx 的时候实际执行逻辑和流程
前端·javascript·前端框架
竹秋…3 小时前
el-table 滚动条小箭头点不了且部分滚动条无法拖动的问题
javascript·vue.js·elementui
做怪小疯子3 小时前
JavaScript 中Array 整理
开发语言·前端·javascript
六元七角八分4 小时前
CSDN文章如何转出为PDF文件保存
开发语言·javascript·pdf
香香爱编程4 小时前
Electron里的electron-window-state 使用
前端·javascript·vue.js·vscode·electron·前端框架
涔溪4 小时前
Vue 中实现 PDF 文件上传
javascript·vue.js·pdf
JohnYan4 小时前
Bun技术评估 - 29 Docker集成
javascript·后端·docker
安卓开发者4 小时前
第14讲:HTTP网络请求 - Dio库的使用与封装
网络·网络协议·http