AJAX-笔记(持续更新中)

文章目录

    • Day1 Ajax入门
      • 1.AJAX概念和axios的使用
      • 2. 认识URL
      • 3.URL的查询参数
      • 4.常用的请求方法和数据提交
      • 5.HTTP协议-报文
      • 6.接口文档
      • 7.form-serialize插件
      • 8.案例用户登录
    • Day2 Ajax综合案
      • bootstrap弹框
      • 图书管理
      • 图片上传
      • 更换背景
      • 个人信息设置
    • Day3 AJAX原理
      • XMLHttpRequest
      • Promise
      • 封装简易版axios
      • 案例-天气预报
    • Day4 AJAX进阶
      • 同步代码和异步代码
      • 回调函数地狱和Promise链式调用
      • async和await使用
      • 事件循环(EventLoop)
      • 宏任务与微任务-执行任务
      • Promise.all静态方法
      • 商品分类
      • 学习反馈
    • 总结

资料:
素材与资料都来自黑马程序员
思维导图
mdn网址

Day1 Ajax入门

1.AJAX概念和axios的使用

在这里插入图片描述
概念:AJAX是浏览器与服务器进行数据通信的技术
作用:浏览器和服务器之间通信,动态数据交互。
怎么使用AJAX?

1.先使用axios库,与服务器进行数据通信(使用场景:VUE,reat项目都会用到axios)
2.再学习XMLHttpREquest对象的使用,理解AJAX底层原理

axios使用:

  • 1.引入axios库:
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  • 2.使用axios函数
    √ 传入配置对象
    √ 再用.then回调函数接收结果,并做后续的处理
axios({url:'目标资源地址'
}).then(result => {
//对服务器进行后续的处理
})

2. 认识URL

URL:统一资源定位符,网址,用于访问服务器资源
解释url每个部分的作用:

http://hmajax.itheima.net /api/login
协议域名 资源路径

在这里插入图片描述

3.URL的查询参数

定义:浏览器提供给服务器额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
URL的查询参数的作用:浏览器提供给服务器额外信息,获取对应的数据
axios-查询参数:
使用params选项,携带参数名和值
axios在运行时把参数名和值,会拼接到url?参数名=值

axios({url:'目标资源地址',params:{参数名:值
}).then(result => {
//对服务器进行后续的处理
})

4.常用的请求方法和数据提交

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

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

数据提交:当数据需要在服务器上保存
axios请求配置:

  • url:请求的URL网址
  • method:请求的方法,GET可以省略(不区分大小写)
  • data:提交数据
axios({url:'目标资源地址',params:{参数名:值},data:{参数名:值}
}).then(result => {
//对服务器进行后续的处理
})

axios-错误处理

axios({//请求选项
}).then(result => {//处理数据
}).catch(error => {//处理错误
})

5.HTTP协议-报文

  • 请求报文:浏览器发送给服务器的内容叫做请求报文
  • 请求报文的组成:

1.请求行:请求方法,URL,协议
2.请求头:以键值对的格式携带的附加信息,比如Content-Type
3.空行:分隔请求头,空行之后的是发送给服务器的资源(感觉我的浏览器有点不一样)
4.请求体:发送的资源

  • 通过Chrome的网络面板查看请求报文

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

响应报文的组成:

  • 1.响应行:协议、Http响应状态码、状态信息
  • 2.响应头:键值对的格式携带的附加信息,比如Content-Type
  • 3.空行:分隔响应头,空行之后的是返回给浏览器的资源
  • 4.响应体:返回的资源
    在这里插入图片描述
    在这里插入图片描述

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

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

6.接口文档

接口文档:由后端提供的描述接口的文章
在这里插入图片描述

7.form-serialize插件

作用:快速收集表单元素的值。
素材:

<!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>13.form-serialize插件使用</title>
</head><body><form action="javascript:;" class="example-form"><input type="text" name="uname"><br><input type="text" name="pwd"><br><input type="button" class="btn" value="提交"></form><!-- 目标:在点击提交时,使用form-serialize插件,快速收集表单元素值--><script>document.querySelector('.btn').addEventListener('click', () => {})</script>
</body></html>
 <script src="./lib/form-serialize.js"></script><script>document.querySelector('.btn').addEventListener('click', () => {/* 2.使用serialize函数,快速收集表单元素的值参数1:要获得哪个表单的数据表单元素设置name属性,值会作为对象的属性名建议name属性的值,最好和接口文档参数名一致参数2:配置对象hash:设置获取数据结构-true:JS对象(推荐) 一般请求体里提交给服务器-false;查询字符串empty:设置是否获取空值-true:获取空值(推荐)数据结构和标签结构一致-false:不获得空值*/const form = document.querySelector('.example-form')//  const data = serialize(form,{hash:true,empty:true})//  const data = serialize(form,{hash:false,empty:true})const data = serialize(form,{hash:true,empty:false})console.log(data);})</script>

8.案例用户登录

素材:

<!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>12.案例_登录_提示消息</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:使用提示框,反馈提示消息// 1.1 登录-点击事件document.querySelector('.btn-login').addEventListener('click', () => {// 1.2 获取用户名和密码const username = document.querySelector('.username').valueconst password = document.querySelector('.password').value// console.log(username, password)// 1.3 判断长度if (username.length < 8) {console.log('用户名必须大于等于8位')return // 阻止代码继续执行}if (password.length < 6) {console.log('密码必须大于等于6位')return // 阻止代码继续执行}// 1.4 基于axios提交用户名和密码// console.log('提交数据到服务器')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)})})</script>
</body></html>
 <script>// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信// 目标2:使用提示框,反馈提示消息// 1.1 登录-点击事件document.querySelector('.btn-login').addEventListener('click', () => {// 1.2 获取用户名和密码const username = document.querySelector('.username').valueconst password = document.querySelector('.password').value// console.log(username, password)// 1.3 判断长度if (username.length < 8) {console.log('用户名必须大于等于8位')return // 阻止代码继续执行}if (password.length < 6) {console.log('密码必须大于等于6位')return // 阻止代码继续执行}// 1.4 基于axios提交用户名和密码// console.log('提交数据到服务器')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)})})</script>

在这里插入图片描述

Day2 Ajax综合案

bootstrap弹框

bootstrap中文文档

  • 属性控制方式
<!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>Bootstrap 弹框</title><!-- 引入bootstrap.css --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head><body><!-- 目标:使用Bootstrap弹框1. 引入bootstrap.css 和 bootstrap.js2. 准备弹框标签,确认结构3. 通过自定义属性,控制弹框的显示和隐藏--><button type="button" class="btn btn-primary" data-bs-target = '.my-box' data-bs-toggle="modal">显示弹框</button><!-- 弹框标签 bootstrap的标签modal弹框:添加modal类名(默认隐藏)--><div class="modal my-box" tabindex="-1"><div class="modal-dialog"><!-- 弹框内容 --><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Modal title</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body"><p>Modal body text goes here.</p></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button><button type="button" class="btn btn-primary">Save changes</button></div></div></div></div><!-- 引入bootstrap.js --><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
</body></html>
  • js属性控制
<!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>Bootstrap 弹框</title><!-- 引入bootstrap.css --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head><body><!-- 目标:使用JS控制弹框,显示和隐藏1. 创建弹框对象2. 调用弹框对象内置方法.show() 显示.hide() 隐藏--><button type="button" class="btn btn-primary edit-btn">编辑姓名</button><div class="modal name-box" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">请输入姓名</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body"><form action=""><span>姓名:</span><input type="text" class="username"></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button><button type="button" class="btn btn-primary save-btn">保存</button></div></div></div></div><!-- 引入bootstrap.js --><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script><script>// q.创建弹框对象const modalDom = document.querySelector('.name-box')const modal = new bootstrap.Modal(modalDom)// 编辑姓名-->点击-->赋予默认姓名 -->弹框显示document.querySelector('.edit-btn').addEventListener('click',()=>{document.querySelector('.username').value = '默认姓名'// 显示弹框modal.show()})
//  保存-->点击--->弹框隐藏document.querySelector('.save-btn').addEventListener('click',()=>{const username = document.querySelector('.username').value console.log('模拟将姓名保存在服务器当中',username);// 隐藏弹框modal.hide()})</script></body></html>

图书管理

步骤如下:

  • 目标1:渲染图书列表
    1.1 获取数据
    1.2 渲染数据

const creator = '老张'
// 封装-获取被渲染图书列表函数
function getBookList(){// 1.1获取数据axios({url:'http://hmajax.itheima.net/api/books',params:{// 外号:获取对应数据creator}}).then(result => {// console.log(result);// console.log(result.data.data);const bookList = result.data.data// 1.2渲染数据const htmlStr = bookList.map((item,index) => {return `<tr><td>${index+1}</td><td>${item.bookname}</td><td>${item.author}</td><td>${item.publisher}</td><td data-id=${item.id}><span class="del">删除</span><span class="edit">编辑</span></td></tr>  `    }).join('')// console.log(htmlStr);document.querySelector('.list').innerHTML = htmlStr})
}
getBookList()
  • 目标2:新增图书
    2.1新增弹框–>显示和隐藏
    2.2 收集表单数据,并提交到服务器保存
    2.3 刷新图示列表
// 2.1创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal =new bootstrap.Modal(addModalDom)
// 保存按钮->点击->隐藏弹框
document.querySelector('.add-btn').addEventListener('click',() => {// 2.2 收集表单数据,并提交到服务器const addForm = document.querySelector('.add-form')const bookObj = serialize(addForm,{hash:true,empty:true})console.log(bookObj);
//   提交到服务器
axios({url:'http://hmajax.itheima.net/api/books',method:'post',data:{...bookObj,creator}
}).then(result => {console.log(result);// 2.3添加成功之后,重新请求并渲染图书列表getBookList()// 重置表单addForm.reset()// 隐藏弹框addModal.hide()})
})
  • 目标3: 删除图书
    3.1 删除元素绑定点击事件 -> 获取图书id
    3.2 调用删除接口
    3.3刷新图书列表

// 3.1 删除元素绑定点击事件 -> 获取图书id
// 事件委托
document.querySelector('.list').addEventListener('click',e => {// 获取触发事件目标元素// 判断点击的是删除元素if(e.target.classList.contains('del')){// console.log('删除元素');// 获取图书id(自定义属性)const theId = e.target.parentNode.dataset.idconsole.log(theId);// 3.2 调用删除接口axios({url:`http://hmajax.itheima.net/api/books/${theId}`,method:'delete'}).then(() => {// 3.3刷新图书列表getBookList()})}
})
  • 目标4:编辑图书
    4.1 编辑弹框->显示和隐藏
    4.2 获取当前编辑图书数据 -> 回显到编辑表单中
    4.3 提交保存修改,并刷新列表
// 4.1 编辑弹框->显示和隐藏
const editDom = document.querySelector('.edit-modal')
const editModal = new bootstrap.Modal(editDom)
// 编辑元素 -> 点击弹框->弹框显示
document.querySelector('.list').addEventListener('click',e => {// 判断点击的是否是编辑元素if(e.target.classList.contains('edit')){// 4.2 获取当前编辑图书数据 -> 回显到编辑表单中const theId = e.target.parentNode.dataset.idaxios({url:`http://hmajax.itheima.net/api/books/${theId}`}).then((result) => {const bookObj = result.data.data// 数据对象“属性”和标签“类名”一致// 遍历数据对象,使用属性去获得对应的标签,快速赋值const keys = Object.keys(bookObj)console.log(keys);// ['id', 'bookname', 'author', 'publisher']keys.forEach(key => {document.querySelector(`.edit-form .${key}`).value = bookObj[key]})})editModal.show()}
})
// 修改按钮->点击->隐藏弹框
document.querySelector('.edit-btn').addEventListener('click',()=>{
// 4.3 提交保存修改,并刷新列表const  editForm = document.querySelector('.edit-form')const{id,bookname,author,publisher} = serialize(editForm,{hash: true,empty:true})
//    保存正在编辑的图书id,隐藏起来:无需用户修改
// <input type="hidden" class="id" name="id" value="230530">axios({url:`http://hmajax.itheima.net/api/books/${id}`,method:'put',data:{bookname,author,publisher,creator}}).then(() => {// 修改成功以后,重新1获取并刷新列表getBookList()})editModal.hide()
})

图片上传

   1. 获取图片文件2. 使用 FormData 携带图片文件3. 提交到服务器,获取图片url网址使用
 <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>//  文件选择元素->change事件document.querySelector('.upload').addEventListener('change',e => {// 1. 获取图片文件// console.dir(e.target)console.log(e.target.files[0]);// 2. 使用 FormData 携带图片文件const fd = new FormData()fd.append('img',e.target.files[0])// 3. 提交到服务器,获取图片url网址使用axios({url:'http://hmajax.itheima.net/api/uploadimg',method:'post',data:fd}).then(result => {console.log(result);// 取出url位置,用img标签加载显示const imgUrl = result.data.data.urldocument.querySelector('.my-img').src = imgUrl})})</script>

更换背景

   目标:网站-更换背景1. 选择图片上传,设置body背景2. 上传成功时,"保存"图片url网址3. 网页运行后,"获取"url网址使用

document.querySelector('.bg-ipt').addEventListener('change',e => {// 1. 选择图片上传,设置body背景// console.log(e.target.files[0]);const fd = new FormData()fd.append('img',e.target.files[0])//  提交到服务器,获取图片url网址使用axios({url:'http://hmajax.itheima.net/api/uploadimg',method:'post',data:fd}).then(result => {//    console.dir(result);  const imgUrl = result.data.data.urldocument.body.style.backgroundImage = `url(${imgUrl})`// 2. 上传成功时,"保存"图片url网址localStorage.setItem('bgImg',imgUrl)})
})// 网页运行后,"获取"url网址使用
const bgUrl = localStorage.getItem('bgImg')
console.log(bgUrl);
bgUrl &&  (document.body.style.backgroundImage = `url(${bgUrl})`)

个人信息设置

  目标1:信息渲染1.1 获取用户的数据1.2 回显数据到标签上

const creator = '张三'
axios({url:`http://hmajax.itheima.net/api/settings`,params:{creator}
}).then(result => {const userObj = result.data.dataconsole.log(userObj);// 1.2回显数据到标签上Object.keys(userObj).forEach(key => {if(key === 'avatar'){// 赋予默认头像document.querySelector('.prew').src = userObj[key]}else if(key === 'gender'){// 赋予默认性别// 获取性别单选框:[男radio元素,女radio元素]const gRadioList = document.querySelectorAll('.gender')// 获取性别数字:0男,1女const gNum = userObj[key]// 通过性别数字,作为下标,找到对应性别单选框,设置选中状态gRadioList[gNum].checked = true}else{// 赋予默认值document.querySelector(`.${key}`).value = userObj[key]}})
})
目标2:修改头像2.1 获取头像文件2.2 提交服务器并更新头像

// 文件选择元素->change事件
document.querySelector('.upload').addEventListener('change',e => {// 2.1获取头像console.log(e.target.files[0]);const fd = new FormData()fd.append('avatar',e.target.files[0])fd.append('creator',creator)// 2.2 提交服务器并更新头像axios({url:"http://hmajax.itheima.net/api/avatar",method:'put',data:fd}).then(result => {console.log(result);// data.data.avatarconst imgUrl = result.data.data.avatardocument.querySelector('.prew').src = imgUrl})})

/*

目标3:提交表单3.1 收集表单元素3.2 提交到服务器
目标4:结果显示4.1 创建toast对象4.2 调用show方法-> 显示提示框

// 保存修改-点击
document.querySelector('.submit').addEventListener('click',() => {// 3.1 收集表单元素const userForm = document.querySelector('.user-form')const userObj = serialize(userForm,{hash:true,empty:true})userObj.creator = creator// 性别数字字符串,转成数字类型userObj.gender = +userObj.genderconsole.log(userObj);// 3.2提交给服务器axios({url:"http://hmajax.itheima.net/api/settings",method:'put',data:userObj}).then( result => {// 4.1 创建toast对象const toastDom = document.querySelector('.my-toast')const toast = new bootstrap.Toast(toastDom)// 4.2 调用show方法-> 显示提示框toast.show()})
})

Day3 AJAX原理

XMLHttpRequest

XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX 编程中被大量使用。
AJAX原理:XMLHttpRequest对象;
学习XHR原因:

1.有更多与服务器数据通信方式
2.了解axios内部原理

XHR使用步骤:

  • 创建XHR对象
  • 调用open方法,设置url和请求方法
  • 监听loadend事件,接收结果
  • 调用send方法,发起请求
let xhr = new XMLHttpRequest()
xhr.open('请求方法','请求url网址')
xhr.addEventlistener('loadend',()=>{//响应结果console.log(xhr.response)  接收响应
})
xhr.send() 发送请求

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Promise

概念:表示(管理)一个异步操作最终状态结果值的对象

好处:

1.逻辑清晰
2.了解axios函数内部运作机制
3.能解决回调函数地狱问题

学习promise对象原因:
√ 成功和失败状态,可以管理对于处理程序
√ 了解axios内部原理
promise使用步骤:

  <script>/*** 目标:使用Promise管理异步任务*///  1.创建promise对象(pending待定状态)const p = new Promise((resolve, reject) => {// Promise对象创建,这里的代码都会执行// 2.执行代码setTimeout(() => {// resolve()=>'fulfilled状态--已兑现'=> then()   resolve('模拟AJAX请求-成功结果')// reject()=>'reject状态--已拒绝'=> catch()reject(new Error('模拟AJAX请求-失败结果'))}, 2000)})console.log(p);// 3.获取结果p.then(result => {console.log(result);}).catch(error => {console.log(error);})</script>

在这里插入图片描述

 目标:使用Promise管理XHR请求省份列表1. 创建Promise对象2. 执行XHR异步代码,获取省份列表3. 关联成功或失败函数,做后续处理
 <script>//   1. 创建Promise对象const p = new Promise((resolve,reject)=> {// 2. 执行XHR异步代码,获取省份列表const xhr = new XMLHttpRequest()xhr.open('GET','http://hmajax.itheima.net/api/province')xhr.addEventListener('loadend',()=>{//  xhr如何判断响应成功还是失败的?// 2xx开头的都是成功响应状态码console.log(xhr);if(xhr.status >= 200 && xhr.status < 300){resolve(JSON.parse(xhr.response))}else{reject(new Error(xhr.response))}})xhr.send()})//3. 关联成功或失败函数,做后续处理p.then((result)=>{console.log(result);document.querySelector('.my-p').innerHTML = result.list.join('<br>')}).catch(error=>{// 错误对象要用console.dir详细打印console.dir(error);//  服务器返回错误提示消息,插入p标签document.querySelector('.my-p').innerHTML = error.message}) </script>

封装简易版axios

  目标:封装_简易axios函数_获取省份列表1. 定义myAxios函数,接收配置对象,返回Promise对象2. 发起XHR请求,默认请求方法为GET3. 调用成功/失败的处理程序4. 使用myAxios函数,获取省份列表展示
<script>// 1. 定义myAxios函数,接收配置对象,返回Promise对象function myAxios(config){return new Promise((resolve,reject) =>{// 2. 发起XHR请求,默认请求方法为GETconst xhr = new XMLHttpRequest()xhr.open('GET'||config.method,config.url)//  3. 调用成功/失败的处理程序xhr.addEventListener('loadend',()=>{if(xhr.status >= 200 && xhr.status < 300){resolve(JSON.parse(xhr.response))}else{reject(new Error(xhr.response))}})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.dir(error);document.querySelector('.my-p').innerHTML = error.message})</script>
  目标:封装_简易axios函数_获取地区列表1. 判断有params选项,携带查询参数2. 使用URLSearchParams转换,并携带到url上3. 使用myAxios函数,获取地区列表
<script>function myAxios(config) {if(config.params){const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()config.url = config.url+`?${queryString}`}return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', () => {if (xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})xhr.send()})}myAxios({url:'http://hmajax.itheima.net/api/area',params:{pname:'广东省',cname:'河源市'}}).then((result)=>{console.log(result);document.querySelector('.my-p').innerHTML = result.list.join('<br>')}).catch(error=>{// 错误对象要用console.dir详细打印console.dir(error);//  服务器返回错误提示消息,插入p标签document.querySelector('.my-p').innerHTML = error.message}) </script>
 目标:封装_简易axios函数_注册用户1. 判断有data选项,携带请求体2. 转换数据类型,在send中发送3. 使用myAxios函数,完成注册用户
<script>function myAxios(config) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()if (config.params) {const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()config.url += `?${queryString}`}xhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', () => {if (xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})if(config.data){// 告诉服务器,我传递的内容类型是JSON字符串xhr.setRequestHeader('Content-Type','application/json')// 准备数据并转成JSON字符串xhr.send(JSON.stringify(config.data))}else{xhr.send()}   })}document.querySelector('.reg-btn').addEventListener('click',() =>{myAxios({url:'http://hmajax.itheima.net/api/register',method:'POST',data:{username:'zz111111111222',password:'12345111226'}}).then((result)=>{console.log(result);//  document.querySelector('.my-p').innerHTML = result.list.join('<br>')}).catch(error=>{// 错误对象要用console.dir详细打印console.dir(error);//  服务器返回错误提示消息,插入p标签//  document.querySelector('.my-p').innerHTML = error.message}) })</script>

案例-天气预报

   目标1:默认显示-北京市天气1.1 获取北京市天气数据1.2 数据展示到页面

// 获取并渲染城市天气函数


function getWeather(cityCode){
// 1.1获取北京市天气数据myAxios({url:'http://hmajax.itheima.net/api/weather',params:{city:cityCode }}).then(result => {console.log(result);const wObj = result.data// 1.2数据展示到页面const dateStr = `   <span class="dateShort">${wObj.date}</span><span class="calendar">农历&nbsp;<span class="dateLunar">${wObj.dateLunar}</span>`document.querySelector('.title').innerHTML=dateStr//   城市名字document.querySelector('.area').innerHTML = wObj.area// 当天天气const nowWStr = ` <div class="tem-box"><span class="temp"><span class="temperature">${wObj.temperature}</span><span>°</span></span></div><div class="climate-box"><div class="air"><span class="psPm25">${wObj.psPm25}</span><span class="psPm25Level">${wObj.psPm25Level}</span></div><ul class="weather-list"><li><img src=${wObj.weatherImg} class="weatherImg" alt=""><span class="weather">${wObj.weather}</span></li><li class="windDirection">${wObj.windDirection}</li><li class="windPower">${wObj.windPower}</li></ul></div>`document.querySelector('.weather-box').innerHTML = nowWStr
//   当前天气const twObj = wObj.todayWeatherconsole.log(twObj);const todayWStr = `<div class="range-box"><span>今天:</span><span class="range"><span class="weather">${twObj.weather}</span><span class="temNight">${twObj.temNight}</span><span>-</span><span class="temDay">${twObj.temDay}</span><span>℃</span></span>
</div>
<ul class="sun-list"><li><span>紫外线</span><span class="ultraviolet">${twObj.ultraviolet}</span></li><li><span>湿度</span><span class="humidity">${twObj.humidity}</span>%</li><li><span>日出</span><span class="sunriseTime">${twObj.sunriseTime}</span></li><li><span>日落</span><span class="sunsetTime">${twObj.sunsetTime}</span></li>
</ul>`
document.querySelector('.today-weather').innerHTML =  todayWStr
// 7天天气预报
const dayForecast = wObj.dayForecast
const dayForecastStr = dayForecast.map(item =>{return `<li class="item"><div class="date-box"><span class="dateFormat">${item.dateFormat}</span><span class="date">${item.date}</span></div><img src="${item.weatherImg}" alt="" class="weatherImg"><span class="weather">${item.weather}</span><div class="temp"><span class="temNight">${item.temNight}</span>-<span class="temDay">${item.temDay}</span><span>℃</span></div><div class="wind"><span class="windDirection">${item.windDirection}</span><span class="windPower">&lt;${item.windPower}</span></div></li>`
}).join('')
document.querySelector('.week-wrap').innerHTML=dayForecastStr}).catch(error =>{console.log(error);})
}
//默认进入网页-就要获取天气数据
getWeather('110100')
目标2:搜索城市列表2.1绑定input手机开你,获取关键字2.2获取城市列表数据

// 2.1绑定input手机开你,获取关键字
document.querySelector('.search-city').addEventListener('input',e => {// 2.2获取城市列表数据console.log(e.target.value);myAxios({url:'http://hmajax.itheima.net/api/weather/city',params:{city: e.target.value}}).then(result => {console.log(result);const liStr = result.data.map(item => {return `<li class="city-item" data-code=${item.code}>${item.name}</li>`}).join('')console.log(liStr);const a =document.querySelector('.search-list').innerHTML = liStrconsole.log(a);}).catch(error => {console.dir(error)})
})
目标3:切换城市天气3.1绑定城市点击事件,获取城市code值3.2 调用获取并展示天气的函数
document.querySelector('.search-list').addEventListener('click',e => {if(e.target.tagName === 'LI'){getWeather(e.target.dataset.code)}
})

Day4 AJAX进阶

同步代码和异步代码

同步代码:逐行执行,需原地等待结果后,才继续向下执行
异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数。
Js中的异步代码:setTimeout/setInterval,事件,AJAX

回调函数地狱和Promise链式调用

1.回调函数地狱
在回调函数一直向下嵌套回调函数,形成回调函数地狱
目标:演示回调函数地狱
需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱
缺点:可读性差,异常无法获取,耦合性严重,牵一发动全身

 <script>axios({url:'http://hmajax.itheima.net/api/province'}).then(result => {const pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2.获取默认第一个城市的名字axios({url:'http://hmajax.itheima.net/api/city', params:{pname}}).then(result => {const cname = result.data.list[0]document.querySelector('.city').innerHTML = cname// 3.获取默认第一个地区的名字axios({url:'http://hmajax.itheima.net/api/area',params:{pname,cname}}).then(result => {const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})})})</script>

2.Promise的链式调用–入门
概念:依靠then()方法会返回一个新生成的Promise对象特性,继续初恋下一环任务,直到结束
细节:then()回调函数中的返回值,会影响新生成的Promise对象最终状态和结果
目标:掌握Promise的链式调用
需求:把省市的嵌套结构,改成链式调用的线性结构

  <script>//  1.创建Promise对象-模拟请求省份名字const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('北京市')}, 2000)})// 2.获取省份的名字const p2 = p.then(result => {return new Promise((resolve, reject) => {setTimeout(() => {resolve(result + '-----北京市')}, 2000)})})// 4.获取城市名字p2.then(result => {console.log(result);})</script>

在这里插入图片描述
3.解决回调函数地狱

目标:把回调函数嵌套代码,改成Promise链式调用结构
需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
 <script>let pname = ''axios({url:'http://hmajax.itheima.net/api/province'}).then(result => {pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2.获取默认第一个城市的名字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.获取默认第一个地区的名字return axios({url:'http://hmajax.itheima.net/api/area',params:{pname,cname}}).then(result => {const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})})})

async和await使用

概念;在async函数内,使用await关键字取代then函数,等待获取Promise对象成功状态的结果值
async函数和await捕获错误:使用 try…catch…

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:掌握async和await语法,解决回调函数地狱* 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值* 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)*///  1.定义async修饰函数async function getData(){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/area1',params:{pname,cname}})const areaName = aObj.data.list[0]document.querySelector('.province').innerHTML = pnamedocument.querySelector('.city').innerHTML = cnamedocument.querySelector('.area').innerHTML = areaName} catch (error) {/* error接收的是,错误信息try里代码,如果有错误,直接进入这里执行*/console.dir(error);}}getData()</script>

在这里插入图片描述

在这里插入图片描述

事件循环(EventLoop)

概念:JavaScript 有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其他语言中的模型截然不同,比如 C 和 Java。
原因;JavaScript单线程(某一时刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环模型。
JavaScript内代码如何执行?

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

 <script>/*** 目标:阅读并回答执行的顺序结果*/console.log(1)setTimeout(() => {console.log(2)}, 0)console.log(3)setTimeout(() => {console.log(4)}, 2000)console.log(5)</script>

事件循环练习

 <script>/*** 目标:阅读并回答执行的顺序结果* 1 5 3 2 4 6(点击时触发)*/console.log(1)setTimeout(() => {console.log(2)}, 0)function myFn() {console.log(3)}function ajaxFn() {const xhr = new XMLHttpRequest()xhr.open('GET', 'http://hmajax.itheima.net/api/province')xhr.addEventListener('loadend', () => {console.log(4)})xhr.send()}for (let i = 0; i < 1; i++) {console.log(5)}ajaxFn()document.addEventListener('click', () => {console.log(6)})myFn()</script>

事件·循环·练习

宏任务与微任务-执行任务

宏任务 :浏览器执行的异步代码,例如:JS执行脚本事件,setTimeout/setInterval,AJAX请求完成事件,用户交互事件等。

微任务:JS引擎执行的异步代码,例如:Promise对象.then()的回调
JavaScript内代码如何执行?

1.执行第一个script脚本时间宏任务,里面同步代码
2.遇到宏任务/微任务交给宿主环境,有结果回调函数进入对应队列
当执行栈空闲时,清空微任务队列,再执行下一个宏任务,从1再来

  <script>// 目标:回答代码执行顺序console.log(1)setTimeout(() => {console.log(2)const p = new Promise(resolve => resolve(3))p.then(result => console.log(result))}, 0)const p = new Promise(resolve => {setTimeout(() => {console.log(4)}, 0)resolve(5)})p.then(result => console.log(result))const p2 = new Promise(resolve => resolve(6))p2.then(result => console.log(result))console.log(7)</script>

事件循环-执行过程

Promise.all静态方法

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

在这里插入图片描述

 <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:掌握Promise的all方法作用,和使用场景* 业务:当我需要同一时间显示多个请求的结果时,就要把多请求合并* 例如:默认显示"北京", "上海", "广州", "深圳"的天气在首页查看* code:* 北京-110100* 上海-310100* 广州-440100* 深圳-440300*///  1.请求城市天气,得到Promise对象const bjObj = axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'110100'}})const shObj = axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'310100'}})const gzObj = axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'440100'}})const szObj = axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'440300'}})//  console.log(bjObj,shObj, gzObj,szObj);// 2.使用 Promise.all,合并对各Promise对象const p = Promise.all([bjObj,shObj, gzObj,szObj])p.then(result => {console.log(result);// 注意:结果数组顺序和合并时顺序是一致的const htmlStr = result.map(item => {// 解构赋值const {area,weather}=item.data.datareturn `<li>${area}-----${weather}</li>`  }).join('')document.querySelector('.my-ul').innerHTML = htmlStr}).catch(error => {console.dir(eerror)})</script>

商品分类

   目标:把所有商品分类“同时”渲染到页面上1. 获取所有一级分类数据2. 遍历id,创建获取二级分类请求3. 合并所有二级分类Promise对象4. 等待同时成功后,渲染页面
 <script>// 1. 获取所有一级分类数据axios({url:'http://hmajax.itheima.net/api/category/top'}).then(result => {console.log(result);// 2. 遍历id,创建获取二级分类请求const promiseList = result.data.data.map(item =>{return axios({url:'http://hmajax.itheima.net/api/category/sub',params:{id:item.id}})})console.log(promiseList);// 3. 合并所有二级分类Promise对象const p = Promise.all(promiseList)p.then(result => {console.log(result);// 4. 等待同时成功后,渲染页面const htmlStr = result.map(item => {const obj = item.data.datareturn`<div class="item"><h3>一级分类名字:${obj.name}</h3><ul>${obj.children.map(item => {return `  <li><a href="javascript:;"><img src=${item.picture}"><p>${item.name}</p></a></li>`}).join('')}</ul></div>`}).join('')document.querySelector('.sub-list').innerHTML = htmlStr})})</script>

在这里插入图片描述

学习反馈

 目标1:完成省市区下拉列表切换1.1 设置省份下拉菜单数据1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单1.3 切换城市,设置地区下拉菜单数据

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  目标2:收集数据保存2.1 监听提交的点击事件2.2 依靠插件收集表单数据2.3 基于axios提交保存

在这里插入图片描述

/*** 目标1:完成省市区下拉列表切换*  1.1 设置省份下拉菜单数据*  1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单*  1.3 切换城市,设置地区下拉菜单数据*/
// 1.1 设置省份下拉菜单数据
axios({url:'http://hmajax.itheima.net/api/province'}).then(result => {const optionStr = result.data.list.map(item => {return `  <option value="${item}">${item}</option>`}).join('')document.querySelector('.province').innerHTML=`<option value="">省份</option>`+optionStr
})// 1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单
document.querySelector('.province').addEventListener('change',async e => {// 获取用户选择的省份名字console.log(e.target.value);const result = await axios({url:'http://hmajax.itheima.net/api/city',params:{pname:e.target.value}}).then(result =>{const optionStr = result.data.list.map(item => {return `  <option value="${item}">${item}</option>`}).join('')// 把默认初始选项+下属城市数据插入select中   document.querySelector('.city').innerHTML=`<option value="">城市</option>`+optionStr //    清空地区数据document.querySelector('.area').innerHTML= `<option value="">地区</option>`})
})// 1.3 切换城市,设置地区下拉菜单数据document.querySelector('.city').addEventListener('change',async e => {console.log(e.target.value);const result = await axios({url:'http://hmajax.itheima.net/api/area',params:{pname: document.querySelector('.province').value,cname:e.target.value}}).then(result =>{const optionStr = result.data.list.map(item => {return `  <option value="${item}">${item}</option>`}).join('')document.querySelector('.area').innerHTML=`<option value="">地区</option>`+optionStr })
})
/* 目标2:收集数据保存2.1 监听提交的点击事件2.2 依靠插件收集表单数据2.3 基于axios提交保存
*/
// 2.1 监听提交的点击事件
document.querySelector('.submit').addEventListener('click',async ()=> {// 2.2 依靠插件收集表单数据const form =document.querySelector('.info-form')const data = serialize(form,{hash:true,empty:true})console.log(data);// 2.3 基于axios提交保存try {const result = await axios({url:'http://hmajax.itheima.net/api/feedback',method:'post',data })console.log(result);alert(result.data.message)} catch (error) {console.dir(error);alert(error.response.data.message)}})

总结

学习了这门课程,AJAX的大概知识我都清楚了,也在学习过程中,我得到了一些学习经验,比如,看完一天的视频,要回去复习,不然容易忘记,边看视频边敲代码边理解或者看完一天视频再敲代码,可能带着回忆的状态,这样子可以检验自己是否真的懂(可能这个方法会好一点,因人而异),还有就是代码也不是敲一遍就行的,最多敲三遍,最后一遍一定是自己明白了,在不借助外力的情况下,自己敲(虽然但是,我还没达到那种境界,在努力中)。
最后送大家一句话:博学之,审问之,慎思之,明辨之,笃行之。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/33126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL常见命令语句

1.连接数据库 mysql (-h IP) -u root -p 密码2.查看数据库 show databases3.使用数据库 use db_name4.查看表 show tables [from db_name]5.查看表结构 desc tb_name6.创建、删除、选择数据库 create database db_namedrop database db_nameuse db_name7.数据类型 参考链…

使用 API Gateway Integrator 在 Quarkus 中实施适用于 AWS Lambda 的 OpenAPI

AWS API Gateway 集成使得使用符合 OpenAPI 标准的 Lambda Function 轻松实现 REST API。 关于开放API 它是一个 允许以标准方式描述 REST API 的规范。 OpenAPI规范 (OAS) 为 REST API 定义了与编程语言无关的标准接口描述。这使得人类和计算机都可以发现和理解服务的功能&am…

HTML5基础

1、HTML5概述 2014年10月28日&#xff0c;W3C&#xff08;world wide web consortium&#xff0c;万维网联盟&#xff09;的HTML工作组发布了HTML5的正式推荐标准。HTML5作为构建开放Web平台的核心&#xff0c;增加了支持Web应用的许多新特性&#xff0c;以及更符合开发者使用…

git 使用远端代码强制覆盖本地

有时候会遇到这种情景&#xff0c;我们本地的代码不需要了&#xff0c;需要使用远端的代码强制覆盖&#xff0c;这时候可以使用下面的命令 git fetch --all然后再执行下面的命令&#xff0c;重置为远端的代码&#xff0c;即使用远端的代码将本地覆盖 origin/远端分之名 git re…

编译Linux的时候出现 Restart config...

环境 buildroot 问题 在buildroot路径下执行 make linux-rebuild 出现了Restart config… 的问题 原因 我在修改linux源码的时候&#xff0c;在没有指定ARCH架构的情况下&#xff0c; 直接去linux源码目录(output/build/linux/)下执行了 make menuconfig并覆盖了原来的.c…

opencv基础53-图像轮廓06-判断像素点与轮廓的关系(轮廓内,轮廓上,轮廓外)cv2.pointPolygonTest()

点到轮廓的距离 在 OpenCV 中&#xff0c;函数 cv2.pointPolygonTest()被用来计算点到多边形&#xff08;轮廓&#xff09;的最短距离&#xff08;也 就是垂线距离&#xff09;&#xff0c;这个计算过程又称点和多边形的关系测试。该函数的语法格式为&#xff1a; retval cv2…

备战秋招012(20230808)

文章目录 前言一、今天学习了什么&#xff1f;二、动态规划1.概念2.题目 总结 前言 提示&#xff1a;这里为每天自己的学习内容心情总结&#xff1b; Learn By Doing&#xff0c;Now or Never&#xff0c;Writing is organized thinking. 提示&#xff1a;以下是本篇文章正文…

2021年12月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:输出整数部分 输入一个双精度浮点数f, 输出其整数部分。 时间限制:1000 内存限制:65536 输入 一个双精度浮点数f(0 < f < 100000000)。 输出 一个整数,表示浮点数的整数部分。 样例输入 3.8889 样例输出 3 下面是一个使用C语言编写的输出双精度浮点数整数部分…

HTML详解连载(1)

HTML详解连载&#xff08;1&#xff09; HTML定义HTML 超文本标记语言标签语法注意拓展 HTML基本骨架解释VS Code 快速生成骨架&#xff1a;标签的关系父子关系&#xff08;嵌套关系&#xff09;兄弟关系&#xff08;并列关系&#xff09; 代码格式注释 标题标签标签名:h1-h6(双…

制造业企业数字化转型之设备数据采集

导 读 ( 文/ 1894 ) 随着信息技术的快速发展和制造业的转型升级&#xff0c;企业数字化转型已成为保持竞争力和实现可持续发展的关键。在数字化转型过程中&#xff0c;设备数据采集作为重要的一环&#xff0c;发挥着关键的作用。设备数据采集通过收集、分析和利用设备所产生的数…

【资讯速递】AI与人类思维的融合;OpenAI在中国申请注册“GPT-5”商标;移动大模型主要面向to B 智能算力是未来方向

2023年8月11日 星期五 癸卯年六月廿五 第000001号 欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于IT资讯速递专栏,本专栏主要用于发布各种IT资讯&#xff0c;为大家可以省时省力的就能阅读和了解到行业的一些新资讯 资…

Effective Java笔记(28)列表优于数组

数组与泛型相比&#xff0c;有两个重要的不同点 。 首先&#xff0c;数组是协变的&#xff08; covariant &#xff09; 。 这个词听起来有点吓人&#xff0c;其实只是表示如果 Sub 为 Super 的子类型&#xff0c;那么数组类型 Sub[ ]就是Super[ ]的子类型。 相反&#xff0c;泛…

无涯教程-Perl - link函数

描述 此函数创建一个新文件名NEWFILE,链接到文件OLDFILE。该函数创建一个硬链接&#xff1b;如果需要符号链接,请使用符号链接功能。 语法 以下是此函数的简单语法- link OLDFILE,NEWFILE返回值 如果失败,此函数返回0,如果成功,则返回1。 例 以下是显示其基本用法的示例…

开发一个RISC-V上的操作系统(六)—— 中断(interrupt)和异常(exception)

目录 往期文章传送门 一、控制流 &#xff08;Control Flow&#xff09;和 Trap 二、Exceptions, Traps, and Interrupts Contained Trap Requested Trap Invisible Trap Fatal Trap 异常和中断的异同 三、RISC-V的异常处理 mtvec&#xff08;Machine Trap-Vector Ba…

内生安全构建数据存储

一、数据安全成为防护核心&#xff0c;存储安全防护不容有失 1、数据作为企业的核心资产亟需重点保护&#xff0c;数据安全已成网络空间防护核心 2、国家高度重视关键信息基础设施的数据安全&#xff0c;存储安全已成为审核重点 二、存储安全是数据安全的关键一环&#xff0c;应…

AIGC技术揭秘:探索火热背后的原因与案例

文章目录 什么是AIGC技术&#xff1f;为何AIGC技术如此火热&#xff1f;1. 提高效率与创造力的完美结合2. 拓展应用领域&#xff0c;创造商业价值3. 推动技术创新和发展 AIGC技术案例解析1. 艺术创作&#xff1a;生成独特的艺术作品2. 内容创作&#xff1a;实时生成各类内容3. …

SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系

SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 1 SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 1 SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 https://www.swrjzxw.com/1556.html SolidWorks装配体时 显示 不能使用选择如允许此选…

哪些CRM的报价公开且透明?

企业在选型时&#xff0c;会发现很多品牌的CRM系统价格并不透明&#xff0c;往往都是需要跟产品顾问沟通后才能了解。下面推荐一款价格实在的CRM系统&#xff0c;所有报价公开透明&#xff0c;那就是Zoho CRM。 Zoho CRM是什么&#xff1f; Zoho CRM是一款在线CRM软件&#x…

分布式测试插件 pytest-xdist 使用详解

目录 使用背景&#xff1a; 使用前提&#xff1a; 使用快速入门&#xff1a; 使用小结&#xff1a; 使用背景&#xff1a; 大型测试套件&#xff1a;当你的测试套件非常庞大&#xff0c;包含了大量的测试用例时&#xff0c;pytest-xdist可以通过并行执行来加速整体的测试过…

如何使用ChatGPT设计LOGO,只需知道品牌名字就能完成傻瓜式操作

​独特且引人注目的LOGO对于引导用户/消费者快速识别并与你建立联系至关重要。然而&#xff0c;聘请专业的设计师来创建个性化LOGO可能非常昂贵。这里可以使用使用ChatGPT。[1] 你只需要&#xff1a; 准备好公司名称&#xff1b; 能用ChatGPT&#xff0c;用来给BingChat喂log…