1. HTTP 数据请求
相关资源:
- 图片素材📎图片素材.zip
接口文档
1. HTTP 数据请求
什么是HTTP数据请求:
(鸿蒙)应用软件可以通过(鸿蒙)系统内置的 http 模块 和 Axios,通过 HTTP 协议和服务器进行通讯
学习核心Http请求技术:
- Http模块 - 属于鸿蒙内置模块,安全性较高,如果是银行项目都是Http模块
- Axios模块(第三方) - C端(B端)项目可以用开源的axios模块
- 鸿蒙、android,iOS 的原生App开发无需考虑跨域问题
2. http模块基本用法
咱们来看看 http 模块如何使用
传送门
// 1. 导入模块
import { http } from '@kit.NetworkKit'// 2. 创建请求对象
const request = http.createHttp();// 3. 调用request方法进行服务器请求
request.request('Url地址?key1=value1&key2=value2',{//GET(默认请求方式)、POST、PUT、DELETE,method:http.RequestMethod.GET, // 如果是Get之外的请求->必填//OBJECT:服务器返回数据类型自动转换成对象(方便调用)// STRING:服务器返回的数据是一个字符串expectDataType:http.HttpDataType.OBJECT, // 必填// 设置请求头为json格式header:{ // 选填:Get请求有参数时+POST+PUT请求必填,其他选填'Content-Type':'application/json'},// 用来给Get,POST,PUT携带参数用// Get请求: url?key=value// POST,PUT请求:在请求体中携带// 选填:Get请求有参数时+POST+PUT请求必填,其他选填extraData:{// 'key':'value' //具体值来自接口文档pname:'湖南省'}
}).then((res:http.HttpResponse)=>{// 成功响应console.log(JSON.stringify(res.result))}).catch((err:Error)=>{// 失败处理console.log(JSON.stringify(err))})
注意:
- 预览器 和 模拟器 以及真机都可以发送请求
-
- 预览器无需配置网络权限即可成功发送请求
- 【模拟器】和【真机】需要配置网络权限才能成功发送请求
- 配置权限 -> 详细权限设置,可以参考 声明权限 权限列表
-
- 需要在项目的src/main/module.json5(模块配置)下添加如下代码
{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone","tablet","2in1"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","requestPermissions": [{"name": "ohos.permission.INTERNET"}],"abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ets","description": "$string:EntryAbility_desc","icon": "$media:layered_image","label": "$string:EntryAbility_label","startWindowIcon": "$media:startIcon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]}]}
}
2.1. Get请求演示
获取一条随机笑话:https://api-vue-base.itheima.net/api/joke
import { http } from '@kit.NetworkKit'@Entry
@Component
struct Notebook_use {@State message: string = 'Hello World';build() {Row() {Column() {Text(this.message).fontSize(20)Button('看笑话').onClick(() => {const req = http.createHttp()req.request('https://api-vue-base.itheima.net/api/joke',{method: http.RequestMethod.GET,expectDataType:http.HttpDataType.STRING}).then((res: http.HttpResponse) => {// AlertDialog.show({ message: JSON.stringify(res,null,2) })this.message = res.result.toString()})})}.width('100%')}.height('100%')}
}
获取新闻列表数据:https://hmajax.itheima.net/api/news
import { http } from '@kit.NetworkKit'interface NewsResponse {message: stringdata: News[]
}interface News {id: numbertitle: stringsource: stringcmtcount: numberimg: stringtime: string
}@Entry
@Component
struct Day01_02_URL {@State data: NewsResponse | null = nullbuild() {Column() {Button('获取新闻列表数据').onClick(() => {// 1. 创建请求对象const req = http.createHttp()// 2. 发送请求获取服务器数据// http://hmajax.itheima.net/api/newsreq.request('http://hmajax.itheima.net/api/news', {expectDataType: http.HttpDataType.OBJECT}).then(res => {console.log(JSON.stringify(res.result))this.data = res.result as NewsResponse})})// Text(JSON.stringify(this.data,null,2))}.height('100%').width('100%')}
}
地址:http://hmajax.itheima.net/api/city
说明获取某个省所有的城市查询
参数名:pname
说明: 传递省份或直辖市名,比如 北京、广东省…
import { http } from '@kit.NetworkKit'@Entry
@Component
struct Index {build() {Column() {Button('获取城市信息').onClick(() => {const req = http.createHttp()req.request('http://hmajax.itheima.net/api/city', {expectDataType:http.HttpDataType.OBJECT,extraData:{pname:'广东省'}}).then(res=>{console.log(JSON.stringify(res.result))}).catch((err:Error)=>{console.log(JSON.stringify(err,null,2))})})}.height('100%').width('100%')}
}
2.2. POST请求演示
注册用户:接口文档
@Entry
@Component
struct Day01_05_SubmitData {@State username: string = ''@State password: string = ''build() {Column({ space: 15 }) {Text('请求方法和数据提交').fontSize(30).fontWeight(FontWeight.Bold)// $$this.username 双向数据绑定TextInput({ text: $$this.username, placeholder: '用户名' })TextInput({ text: $$this.password, placeholder: '密码' }).type(InputType.Password)Button('注册').width('100%').onClick(() => {Button('登录').width('100%').onClick(() => {})}.width('100%').height('100%').padding(20)}
}
import http from '@ohos.net.http'const req = http.createHttp()@Entry
@Component
struct Day01_05_SubmitData {@State username: string = 'itheima522'@State password: string = '123456'build() {Column({ space: 15 }) {Text('请求方法和数据提交').fontSize(30).fontWeight(FontWeight.Bold)TextInput({ text: $$this.username, placeholder: '用户名' })TextInput({ text: $$this.password, placeholder: '密码' }).type(InputType.Password)Button('注册').width('100%').onClick(() => {req.request('http://hmajax.itheima.net/api/register', {method: http.RequestMethod.POST,expectDataType:http.HttpDataType.OBJECT,header: {contentType: 'application/json'},extraData: {username: this.username,password: this.password}}).then(res => {AlertDialog.show({ message:JSON.stringify(res.result,null,2) })})}) }.width('100%').height('100%').padding(20)}
}
2.3. 模拟器和真机网络权限配置
预览器的网络请求无需配置网络请求权限。
模拟器和真机必须要配置网络权限才能进行网络请求
如果没有配置网络请求权限,则在请求后会出现如下错误:
如何配置网络权限?
在项目中找到entry/src/main/module.json5 文件,在里面配置网络请求
权限列表
{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone","tablet","2in1"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","requestPermissions": [{"name": "ohos.permission.INTERNET"}],"abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ets","description": "$string:EntryAbility_desc","icon": "$media:layered_image","label": "$string:EntryAbility_label","startWindowIcon": "$media:startIcon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]}],"extensionAbilities": [{"name": "EntryBackupAbility","srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets","type": "backup","exported": false,"metadata": [{"name": "ohos.extension.backup","resource": "$profile:backup_config"}]}]}
}
3. 案例-开心一笑
接下来完成一个案例,需求:
- 默认获取若干条笑话,并渲染到页面上
- 下拉刷新
- 触底加载更多
- 点击返回顶部
3.1. 前置知识
3.1.1. Refresh下拉刷新容器组件
作用:可以实现下拉刷新功能
@Entry
@Component
struct Index {// 1. 控制Refresh组件的下拉动画效果的,true:打开下拉刷新效果 false:关闭下拉刷新效果@State isrefreshing: boolean = falsebuild() {Column() {Refresh({ refreshing: $$this.isrefreshing }) {List({ space: 5 }) {ForEach([1, 2, 3, 4, 5, 6, 7, 8], () => {ListItem() {Row() {}.height(100).width('100%').backgroundColor(Color.Pink)}})}}// 只要一下拉就会触发这个事件.onRefreshing(() => {// AlertDialog.show({ message: 'ok' })setTimeout(() => {this.isrefreshing = false // 关闭刷新}, 3000)})}.height('100%').width('100%')}
}
3.1.2. LoadingProgress正在加载中的动画图标
LoadingProgress().height(50).color(Color.Red)
3.1.3. List的触底事件 .onReachEnd()
作用:可以实现List列表数据触底时加载
@Entry
@Component
struct Index {@State isLoding: boolean = falsebuild() {Column() {List({ space: 5 }) {ForEach([1, 2, 3, 4, 5, 6, 7, 8], () => {ListItem() {Row() {}.height(100).width('100%').backgroundColor(Color.Pink)}})// 加一个正在加载中的动画ListItem() {LoadingProgress().height(50)}.width('100%')}// onReachEnd当List的滚动条滚动到底部的时候会触发// ✨✨问题:鼠标一抖动触发了/* 解决方案:设置一个状态变量初始值为false,在onReachEnd中加一个if判断 -> 方法体里面将这个变量的值设置为true,直到服务器返回了数据后,重置这个变量的值为false✨✨onReachEnd特点:页面加载的时候从服务器获取到数据之后会自动触发*/.onReachEnd(() => {// 我们可以发请求拿新数据if (this.isLoding == false) {this.isLoding = truesetTimeout(() => {AlertDialog.show({ message: '触底加载' })this.isLoding = false}, 3000)}})}.height('100%').width('100%')}
}
3.2. 基本结构
/*** 1. 默认加载* 2. 下拉刷新* 3. 触底加载更多* 4. 点击返回顶部* */
@Entry
@Component
struct Day01_07_Jokes {@State jokes: string [] = ['笑话 1']build() {Column() {// 顶部this.HeaderBuilder()// 笑话列表List({ space: 10 }) {ForEach(this.jokes, (joke: string) => {ListItem() {Column({ space: 10 }) {Text('笑话标题').fontSize(20).fontWeight(600)Row({ space: 15 }) {titleIcon({ icon: $r('app.media.ic_public_time'), info: '2024-1-1' })titleIcon({ icon: $r('app.media.ic_public_read'), info: '阅读(6666)' })titleIcon({ icon: $r('app.media.ic_public_comments'), info: '评论(123)' })}Text(joke).fontSize(15).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start).padding(20)}.borderRadius(10).backgroundColor(Color.White).shadow({ radius: 2, color: Color.Gray })})}.padding(10).layoutWeight(1)}.width('100%').height('100%').backgroundColor('#f6f6f6')}@BuilderHeaderBuilder() {Row() {Image($r('app.media.ic_public_drawer_filled')).width(25);Image($r('app.media.ic_public_joke_logo')).width(30)Image($r('app.media.ic_public_search')).width(30);}.width('100%').justifyContent(FlexAlign.SpaceBetween).height(60).padding(10).border({ width: { bottom: 2 }, color: '#f0f0f0' }).backgroundColor(Color.White)}
}@Component
struct titleIcon {icon: ResourceStr = ''info: string = ''build() {Row() {Image(this.icon).width(15).fillColor(Color.Gray)Text(this.info).fontSize(14).fontColor(Color.Gray)}}
}
3.3. 默认获取若干条笑话
核心步骤:
- 生命周期函数中获取数据
-
- aboutToAppear
- http 模块获取笑话,若干条
请求地址:https://api-vue-base.itheima.net/api/joke/list
参数:num
完整url:https://api-vue-base.itheima.net/api/joke/list?num=获取条数
- 将获取到的数据转换格式并渲染
-
- as 类型
import { http } from '@kit.NetworkKit'export interface iItem {code: number;data: string[];msg: string;
}/*** 1. 默认加载 -> 加载五条数据 -> aboutToAppear() -> getList()* 2. 下拉刷新* 3. 触底加载更多* 4. 点击返回顶部* */
@Entry
@Component
struct Day01_07_Jokes {@State jokes: string [] = ['笑话 1']aboutToAppear(): void {this.getList()}// 请求笑话数据async getList() {const req = http.createHttp()try {const res = await req.request('https://api-vue-base.itheima.net/api/joke/list', {expectDataType: http.HttpDataType.OBJECT,extraData: {num: '5'}})// 将res.reslut这个Object对象as成真正的接口类型,才能使用里面的属性const obj = res.result as iItemthis.jokes = obj.data// AlertDialog.show({ message: JSON.stringify(obj.data, null, 2) })} catch (err) {AlertDialog.show({ message: '网络错误' })}}build() {Column() {// 顶部this.HeaderBuilder()// 笑话列表List({ space: 10 }) {ForEach(this.jokes, (joke: string) => {ListItem() {Column({ space: 10 }) {Text('笑话标题').fontSize(20).fontWeight(600)Row({ space: 15 }) {titleIcon({ icon: $r('app.media.ic_public_time'), info: '2024-1-1' })titleIcon({ icon: $r('app.media.ic_public_read'), info: '阅读(6666)' })titleIcon({ icon: $r('app.media.ic_public_comments'), info: '评论(123)' })}Text(joke).fontSize(15).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start).padding(20)}.borderRadius(10).backgroundColor(Color.White).shadow({ radius: 2, color: Color.Gray })})}.padding(10).layoutWeight(1)}.width('100%').height('100%').backgroundColor('#f6f6f6')}@BuilderHeaderBuilder() {Row() {Image($r('app.media.ic_public_drawer_filled')).width(25);Image($r('app.media.ic_public_joke_logo')).width(30)Image($r('app.media.ic_public_search')).width(30);}.width('100%').justifyContent(FlexAlign.SpaceBetween).height(60).padding(10).border({ width: { bottom: 2 }, color: '#f0f0f0' }).backgroundColor(Color.White)}
}@Component
struct titleIcon {icon: ResourceStr = ''info: string = ''build() {Row() {Image(this.icon).width(15).fillColor(Color.Gray)Text(this.info).fontSize(14).fontColor(Color.Gray)}}
}
3.4. 下拉刷新
核心步骤:
- 通过 Refresh组件实现下拉效果
- 在 onRefreshing 中重新获取数据替换默认值即可
- 抽取获取笑话的方法,在 2 个地方调用即可
-
- aboutToAppear
- onRefreshing
-
-
- 延迟关闭下拉刷新的效果
-
/*** 1. 默认加载* 2. 下拉刷新* 3. 触底加载更多* 4. 点击返回顶部* */
import { http } from '@kit.NetworkKit'interface iData {code: numbermsg: stringdata: string[]
}@Entry
@Component
struct Day01_07_Jokes {@State jokes: string [] = ['笑话 1']@State isrefreshing:boolean = false// 1. 页面渲染完成后调用声明周期方法aboutToAppear(): void {this.getList().then(res => {let objData: iData = JSON.parse(res.result.toString())this.jokes = objData.data})}// 获取笑话数据getList() {// 请求服务器数据const req = http.createHttp()// 返回对象return req.request('https://api-vue-base.itheima.net/api/joke/list?num=5')}build() {Column() {// 顶部this.HeaderBuilder()// 笑话列表Refresh({refreshing:$$this.isrefreshing}) {List({ space: 10 }) {ForEach(this.jokes, (joke: string) => {ListItem() {Column({ space: 10 }) {Text(joke.slice(0, 10))// 从字符串中截取前若干个文字.fontSize(20).fontWeight(600)Row({ space: 15 }) {titleIcon({ icon: $r('app.media.ic_public_time'), info: '2024-1-1' })titleIcon({ icon: $r('app.media.ic_public_read'), info: '阅读(6666)' })titleIcon({ icon: $r('app.media.ic_public_comments'), info: '评论(123)' })}Text(joke).fontSize(15).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start).padding(20)}.borderRadius(10).backgroundColor(Color.White).shadow({ radius: 2, color: Color.Gray })})}.padding(10).layoutWeight(1)}.onRefreshing(()=>{// 重新请求服务器获取新数据this.getList().then(res=>{// 刷新列表let objData: iData = JSON.parse(res.result.toString())this.jokes = objData.data//服务器返回数据后,关闭下拉加载功能this.isrefreshing = false })})}.width('100%').height('100%').backgroundColor('#f6f6f6')}@BuilderHeaderBuilder() {Row() {Image($r('app.media.ic_public_drawer_filled')).width(25);Image($r('app.media.ic_public_joke_logo')).width(30)Image($r('app.media.ic_public_search')).width(30);}.width('100%').justifyContent(FlexAlign.SpaceBetween).height(60).padding(10).border({ width: { bottom: 2 }, color: '#f0f0f0' }).backgroundColor(Color.White)}
}@Component
struct titleIcon {icon: ResourceStr = ''info: string = ''build() {Row() {Image(this.icon).width(15).fillColor(Color.Gray)Text(this.info).fontSize(14).fontColor(Color.Gray)}}
}
3.5. 触底加载更多
核心步骤:
- 在 onReachEnd 事件中加载更多数据,list 组件
-
- 重新获取数据
- 和本地的合并到一起
- this.jokes.push(...['笑话 1',’笑话 2‘])
- 获取到的数据和本地数据合并
/*** 1. 默认加载* 2. 下拉刷新* 3. 触底加载更多* 4. 点击返回顶部* */
import { http } from '@kit.NetworkKit'interface iData {code: numbermsg: stringdata: string[]
}@Entry
@Component
struct Day01_07_Jokes {@State jokes: string [] = []@State isrefreshing: boolean = false@State isLoadMore: boolean = false //控制触底加载// 1. 页面渲染完成后调用声明周期方法aboutToAppear(): void {// this.getList()// .then(res => {// let objData: iData = JSON.parse(res.result.toString())// this.jokes = objData.data// })}// 获取笑话数据getList() {// 请求服务器数据const req = http.createHttp()// 返回对象return req.request('https://api-vue-base.itheima.net/api/joke/list?num=5')}build() {Column() {// 顶部this.HeaderBuilder()// 笑话列表Refresh({ refreshing: $$this.isrefreshing }) {List({ space: 10 }) {ForEach(this.jokes, (joke: string) => {ListItem() {Column({ space: 10 }) {Text(joke.slice(0, 10))// 从字符串中截取前若干个文字.fontSize(20).fontWeight(600)Row({ space: 15 }) {titleIcon({ icon: $r('app.media.ic_public_time'), info: '2024-1-1' })titleIcon({ icon: $r('app.media.ic_public_read'), info: '阅读(6666)' })titleIcon({ icon: $r('app.media.ic_public_comments'), info: '评论(123)' })}Text(joke).fontSize(15).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start).padding(20)}.borderRadius(10).backgroundColor(Color.White).shadow({ radius: 2, color: Color.Gray })})// TODO:触底加载更多的动画提示ListItem() {LoadingProgress().height(50)}.width('100%')}.onReachEnd(() => {if (this.isLoadMore == false) {this.isLoadMore = true// 发送新的请求获取新数据新数据应该是追加到this.jokes的后面-> pushthis.getList().then(res => {let objData: iData = JSON.parse(res.result.toString())// 将服务器新返回的数据展开之后追加原数组的后边this.jokes.push(...objData.data)this.isLoadMore = false})}}).padding(10).layoutWeight(1)}.onRefreshing(() => {// 请求服务器获取新数据this.getList().then(res => {let objData: iData = JSON.parse(res.result.toString())this.jokes = objData.data//等服务器返回数据后关闭下拉加载功能this.isrefreshing = false})})}.width('100%').height('100%').backgroundColor('#f6f6f6')}@BuilderHeaderBuilder() {Row() {Image($r('app.media.ic_public_drawer_filled')).width(25);Image($r('app.media.ic_public_joke_logo')).width(30)Image($r('app.media.ic_public_search')).width(30);}.width('100%').justifyContent(FlexAlign.SpaceBetween).height(60).padding(10).border({ width: { bottom: 2 }, color: '#f0f0f0' }).backgroundColor(Color.White)}
}@Component
struct titleIcon {icon: ResourceStr = ''info: string = ''build() {Row() {Image(this.icon).width(15).fillColor(Color.Gray)Text(this.info).fontSize(14).fontColor(Color.Gray)}}
}
3.6. 点击【顶部栏】返回顶部
核心步骤:
- 【顶部栏】点击事件中通过 Scroller控制器 scrollEdge 方法滚到顶部
-
- 通过控制器的方法,滚到顶部即可
/*** 1. 默认加载* 2. 下拉刷新* 3. 触底加载更多* 4. 点击返回顶部* */
import { http } from '@kit.NetworkKit'interface iData {code: numbermsg: stringdata: string[]
}@Entry
@Component
struct Day01_07_Jokes {@State jokes: string [] = []@State isrefreshing: boolean = false@State isLoadMore: boolean = false //控制触底加载listScroller = new ListScroller()// 1. 页面渲染完成后调用声明周期方法aboutToAppear(): void {// this.getList()// .then(res => {// let objData: iData = JSON.parse(res.result.toString())// this.jokes = objData.data// })}// 获取笑话数据getList() {// 请求服务器数据const req = http.createHttp()// 返回对象return req.request('https://api-vue-base.itheima.net/api/joke/list?num=5')}build() {Column() {// 顶部this.HeaderBuilder()// 笑话列表Refresh({ refreshing: $$this.isrefreshing }) {List({ space: 10, scroller: this.listScroller }) {ForEach(this.jokes, (joke: string) => {ListItem() {Column({ space: 10 }) {Text(joke.slice(0, 10))// 从字符串中截取前若干个文字.fontSize(20).fontWeight(600)Row({ space: 15 }) {titleIcon({ icon: $r('app.media.ic_public_time'), info: '2024-1-1' })titleIcon({ icon: $r('app.media.ic_public_read'), info: '阅读(6666)' })titleIcon({ icon: $r('app.media.ic_public_comments'), info: '评论(123)' })}Text(joke).fontSize(15).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start).padding(20)}.borderRadius(10).backgroundColor(Color.White).shadow({ radius: 2, color: Color.Gray })})// TODO:触底加载更多的动画提示ListItem() {LoadingProgress().height(50)}.width('100%')}.onReachEnd(() => {if (this.isLoadMore == false) {this.isLoadMore = true// 发送新的请求获取新数据新数据应该是追加到this.jokes的后面-> pushthis.getList().then(res => {let objData: iData = JSON.parse(res.result.toString())// 将服务器新返回的数据展开之后追加原数组的后边this.jokes.push(...objData.data)this.isLoadMore = false})}}).padding(10).layoutWeight(1)}.onRefreshing(() => {// 请求服务器获取新数据this.getList().then(res => {let objData: iData = JSON.parse(res.result.toString())this.jokes = objData.data//等服务器返回数据后关闭下拉加载功能this.isrefreshing = false})})}.width('100%').height('100%').backgroundColor('#f6f6f6')}@BuilderHeaderBuilder() {Row() {Image($r('app.media.ic_public_drawer_filled')).width(25);Image($r('app.media.ic_public_joke_logo')).width(30)Image($r('app.media.ic_public_search')).width(30);}.onClick(() => {// 点击滚动到顶部this.listScroller.scrollEdge(Edge.Top)}).width('100%').justifyContent(FlexAlign.SpaceBetween).height(60).padding(10).border({ width: { bottom: 2 }, color: '#f0f0f0' }).backgroundColor(Color.White)}
}@Component
struct titleIcon {icon: ResourceStr = ''info: string = ''build() {Row() {Image(this.icon).width(15).fillColor(Color.Gray)Text(this.info).fontSize(14).fontColor(Color.Gray)}}
}
4. 请求库-axios
除了原生的请求库http以外,还可以使用 第三方请求库axios来进行网络请求,为我们提供第二种http请求方式
axios文档传送门
4.1. 基本用法
4.1.1. 下载axios
作为一个第三方库,使用的时候需要先完成下包的操作
打开终端执行命令
# 安装
ohpm i @ohos/axios# 卸载
ohpm uninstall @ohos/axios
ohpm 是一个包管理工具,用来管理鸿蒙提供的第三方模块
如果无法执行命令,或执行失败,可以使用如下方式来完成安装:
4.1.2. axios完成POST请求
基本语法格式:
// 1. 导入axios
// AxiosError:异常时的数据类型
// 正常时的数据类型AxiosResponse 是一个泛型类型
import axios, { AxiosError, AxiosResponse } from '@ohos/axios'// 2. 创建axios的对象实例
const req = axios.create()// 3. 发送POST请求,并提交数据给服务器
const res:AxiosResponse<响应数据类型> = await req<响应数据类型(可以写null), AxiosResponse<响应数据类型>, 请求体数据类型>({method: 'POST', // 请求方法url: 'https://hmajax.itheima.net/api/login', //服务器url地址data: { // 请求体数据username: '黑马no1hello',password: '123456'}})
登录接口传送门
import axios, { AxiosError, AxiosResponse } from '@ohos/axios'// 1. 利用axios.create创建请求对象
const reqeust = axios.create({baseURL: 'https://hmajax.itheima.net/'
})export interface iRes {/*** 业务状态码, 10000成功, 10004-账号/密码未携带*/code: number;/*** 响应数据*/data: object;/*** 响应消息*/message: string;
}export interface iBody {/*** 密码, 最少6位*/password: string;/*** 用户名, 最少8位,中英文和数字组成,*/username: string;
}@Entry
@Component
struct Index {build() {Column() {Button('post请求测试').onClick(async () => {// 2. 发起请求try {const res: AxiosResponse<iRes> = await reqeust<null, AxiosResponse<iRes>, iBody>({method: 'POST',url: 'api/login',data: {username: '黑马no1hello',password: '123456'}})AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })} catch (err) {// 将err异常对象强制转换成 AxiosError// response就是异常的响应对象const error: AxiosError = err as AxiosErrorAlertDialog.show({ message: JSON.stringify(error.response, null, 2) })}})}.height('100%').width('100%').backgroundColor(Color.Pink)}
}
- 请求体有数据提交时,泛型参数 3,需要设置为【请求体】的格式,可以从 apifox 直接c+v
4.1.3. axios完成GET请求
一级商品(无参数) : 接口文档传送门
import axios, { AxiosError, AxiosResponse } from '@ohos/axios'export interface ApifoxModel {/*** 响应数据*/data: Datum[];/*** 响应消息*/message: string;
}export interface Datum {/*** 顶级分类id*/id: string;/*** 顶级分类名字*/name: string;/*** 顶级分类图片*/picture: string;
}@Entry
@Component
struct Index {build() {Column() {Button('axios.get').onClick(async () => {// 1. 创建请求实例const req = axios.create()// 2. async 和 await方式发送get请求(不带参数)try{let res: AxiosResponse<ApifoxModel> = await req({method: 'get',url: 'https://hmajax.itheima.net/api/category/top'})AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })} catch (err) {let errObj: AxiosError = errAlertDialog.show({ message: '出错了:' + JSON.stringify(errObj.message, null, 2) })}// 3. .then().catch()方式发送请求(不带参数)// req.request({// method: 'get',// url: 'https://hmajax.itheima.net/api/category/top1'// })// .then((res: AxiosResponse<ApifoxModel>) => {// AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })// })// .catch((err: AxiosError) => {// AlertDialog.show({ message: '出错了:' + JSON.stringify(err, null, 2) })// })})}.height('100%').width('100%')}
}
get 请求传递的查询参数
import axios, { AxiosError, AxiosResponse } from '@ohos/axios'export interface ApifoxModel {/*** 响应数据*/data: Data;/*** 响应消息*/message: string;
}/*** 响应数据*/
export interface Data {/*** 顶级分类下属二级分类数组*/children: Child[];/*** 顶级分类id*/id: string;/*** 顶级分类名字*/name: string;/*** 顶级分类图片*/picture: string;
}export interface Child {/*** 二级分类id*/id: string;/*** 二级分类名字*/name: string;/*** 二级分类图片*/picture: string;
}@Entry
@Component
struct Index {build() {Column() {Button('axios.get').onClick(async () => {// 1. 创建请求实例const req = axios.create()// 2. async 和 await方式发送get请求(带参数)try{let res: AxiosResponse<ApifoxModel> = await req({method: 'get',url: 'https://hmajax.itheima.net/api/category/sub',params:{id:'1005000'}})// 写法2:let res: AxiosResponse<ApifoxModel> = await req.get('https://hmajax.itheima.net/api/category/sub', {params: {id: '1005000'}})AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })} catch (err) {let errObj: AxiosError = errAlertDialog.show({ message: '出错了:' + JSON.stringify(errObj.message, null, 2) })}// 3. .then().catch()方式发送请求(带参数)// req.request({// method: 'get',// url: 'https://hmajax.itheima.net/api/category/sub',// params:{// id:'1005000'// }// })// .then((res: AxiosResponse<ApifoxModel>) => {// AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })// })// .catch((err: AxiosError) => {// AlertDialog.show({ message: '出错了:' + JSON.stringify(err, null, 2) })// })})}.height('100%').width('100%')}
}
4.2. axios基地址配置
我们可以使用自定义配置新建一个实例
// 基于配置,返回一个 axios 的实例
const req = axios.create({// 基地址,后续请求的时候这部分可以省略baseURL:'https://hmajax.itheima.net'
})
// get 请求 直接写 url 即可let res: AxiosResponse<ApifoxModel> = await req({method: 'get',url: '/api/category/top'
})
AlertDialog.show({ message: JSON.stringify(res) })
import axios, { AxiosResponse } from '@ohos/axios'
const req = axios.create({// ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨// 设置请求url的基地址,它的值一般填写后台数据接口服务器的域名// 注意点,最后要不要带 / 要看下边req.request()中的url中首字符是否有/// 如果有,不带,否则带//✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨baseURL:'https://hmajax.itheima.net'
})export interface iRes {/*** 响应数据*/data: Datum[];/*** 响应消息*/message: string;
}export interface Datum {/*** 顶级分类id*/id: string;/*** 顶级分类名字*/name: string;/*** 顶级分类图片*/picture: string;
}@Entry
@Component
struct Index {build() {Column({ space: 100 }) {Button('axios发送不带参数的请求').onClick(async () => {// const req = axios.create()try {// 此处编写代码let res: AxiosResponse<iRes> = await req({url: '/api/category/top', //由于设置了基地址,所以此处只需要配置请求路径即可method: 'get', //默认值,可以省略})AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })} catch (err) {AlertDialog.show({ message: JSON.stringify(err, null, 2) })}})Button('axios发送带参数的请求').onClick(async () => {// const req = axios.create()try {// 此处编写代码let res: AxiosResponse<iRes> = await req({url: '/api/city', //由于设置了基地址,所以此处只需要配置请求路径即可method: 'get', //默认值,可以省略// get请求的参数是通过固定的属性:params来进行携带// post请求的参数是固定通过:data来携带的params: {pname: '广东省' // 使用axios中文参数值再内部回自动转成url编码,服务器能够正常响应数据}})AlertDialog.show({ message: JSON.stringify(res.data, null, 2) })} catch (err) {AlertDialog.show({ message: JSON.stringify(err, null, 2) })}})}.height('100%').width('100%')}
}
注意:axios和内置的 http 模块在异常的处理上略有不同:
- 内置的 http 模块,http 状态码为异常时,不会响应为错误
- axios对于 http 状态码的错误(2xx 以外),会作为异常处理
5. 综合案例-我的书架-axios
图片素材
我的书架.zip
接口文档
接下来咱们使用 axios 来完成书架案例
5.1. 获取图书列表
5.1.1. 静态结构
@Entry
@Component
struct Index {// 1. 我的书架@BuilderMyBook() {Row() {Image($r('app.media.ic_public_drawer_filled')).height(20)Text('我的书架').fontSize(20).fontWeight(800)Image($r('app.media.ic_public_add')).height(20)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding(10).border({ width: { bottom: 1 }, color: { bottom: 'rgba(0,0,0,0.2)' } })}// 2. 书籍列表@BuilderBookList() {List() {ListItem() {// 布局Row({ space: 10 }) {Image($r('app.media.ic_public_cover')).width(100)Column({ space: 25 }) {Column() {Text('书名:').width('100%').fontSize(20).fontWeight(800)Text('作者:').width('100%').fontSize(14).fontWeight(600).fontColor('rgba(0,0,0,0.4)').padding({ top: 5 })}Text('出版社:').width('100%').fontWeight(600).fontColor('rgba(0,0,0,0.4)')}.layoutWeight(1)}.padding(10)}.swipeAction({end: this.delBuilder()})}}// 3. 删除书籍的构建函数@BuilderdelBuilder() {Column(){Text('删除').backgroundColor(Color.Red).fontColor(Color.White).height('100%').width(60).textAlign(TextAlign.Center)}.padding(10)}build() {Column() {// 1. 我的书架this.MyBook()// 2. 书籍列表this.BookList()}.height('100%').width('100%')}
}
5.1.2. 准备类型模块并导出
由于图书的增,改,列表,详情接口返回的数据对象是一样的。所以我们可以在这些业务中可以共用同一个interface类型,因此,需要进行模块封装并导出
export interface iBookResponse {/*** 响应数组*/data: iBookInfo[];/*** 响应消息*/message: string;
}// 按需导出
export interface iBookInfo {/*** 图书作者*/author: string;/*** 图书名字*/bookname: string;/*** 图书id*/id: number;/*** 图书出版社*/publisher: string;
}
5.1.3. 获取图书数据并渲染
import axios, { AxiosResponse } from '@ohos/axios'
import { iBookInfo, iBookResponse } from './models'
import { router } from '@kit.ArkUI'const req = axios.create()@Entry
@Component
struct Index {@State bookList: iBookInfo[] = []aboutToAppear(): void {this.getBookList()}async getBookList() {try {let res: AxiosResponse<iBookResponse> =await req.request({url: 'https://hmajax.itheima.net/api/books',params:{creator:'ivan'}})this.bookList = res.data.data} catch (err) {AlertDialog.show({message:JSON.stringify(err,null,2)})}}build() {Column() {// 1. 我的书架this.MyBook()// 2. 书籍列表this.BookList()}.height('100%').width('100%')}// 1. 我的书架@BuilderMyBook() {Row() {Image($r('app.media.ic_public_drawer_filled')).height(20)Text('我的书架').fontSize(20).fontWeight(800)Image($r('app.media.ic_public_add')).height(20).onClick(()=>{router.pushUrl({url:'pages/axiosbooks/addBook'})})}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding(10).border({ width: { bottom: 1 }, color: { bottom: 'rgba(0,0,0,0.2)' } })}// 2. 书籍列表@BuilderBookList() {List() {ForEach(this.bookList, (item: iBookInfo) => {ListItem() {// 布局Row({ space: 10 }) {Image($r('app.media.ic_public_cover')).width(100)Column({ space: 25 }) {Column() {Text('书名:'+item.bookname).width('100%').fontSize(20).fontWeight(800)Text('作者:'+item.author).width('100%').fontSize(14).fontWeight(600).fontColor('rgba(0,0,0,0.4)').padding({ top: 5 })}Text('出版社:').width('100%').fontWeight(600).fontColor('rgba(0,0,0,0.4)')}.layoutWeight(1)}.padding(10)}.swipeAction({end: this.delBuilder()})})}}// 3. 删除书籍的构建函数@BuilderdelBuilder() {Column() {Text('删除').backgroundColor(Color.Red).fontColor(Color.White).height('100%').width(60).textAlign(TextAlign.Center)}.padding(10)}
}
5.2. 新增图书
5.2.1. 静态结构
// 导入创建者
import { creator } from './models'@Entry
@Component
struct addPage {@State bookname: string = ''@State author: string = ''@State publisher: string = ''build() {Navigation() {Column({ space: 10 }) {Row() {Text('图书名称:')TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })}Row() {Text('图书作者:')TextInput({ placeholder: '请输入作者名字', text: $$this.author })}Row() {Text('图书出版社:')TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })}Button({ type: ButtonType.Normal }) {Text('保存').fontColor(Color.White).fontWeight(800)}.width('100%').height(40).borderRadius(8)}.height('100%').width('100%').padding(10)}.title('新增图书').titleMode(NavigationTitleMode.Mini)}
}
5.2.2. 新增逻辑实现
// 导入创建者
import axios, { AxiosResponse } from '@ohos/axios'
import { creator, iBookInfoDetial } from './models'
import { promptAction, router } from '@kit.ArkUI';// POST请求体数据类型
export interface iReqeustBody {/*** 新增图书作者*/author: string;/*** 新增图书名字*/bookname: string;/*** 新增图书创建者,自己的外号,和获取图书时的外号相同*/creator: string;/*** 新增图书出版社*/publisher: string;
}@Entry
@Component
struct addPage {@State bookname: string = ''@State author: string = ''@State publisher: string = ''async addBook() {// 1. 非空验证 -> 轻提示用户if (this.bookname == '' || this.author == '' || this.publisher == '') {promptAction.showToast({ message: '图书名,作者,出版社均非空' })return //阻止下面代码继续执行}const req = axios.create()let res: AxiosResponse<iBookInfoDetial> = await req.request<null, AxiosResponse<iBookInfoDetial>, iReqeustBody>({method: 'POST',url: 'https://hmajax.itheima.net/api/books',data: {bookname: this.bookname,author: this.author,publisher: this.publisher,creator: creator}})promptAction.showToast({ message: res.data.message })router.back()}build() {Navigation() {Column({ space: 10 }) {Row() {Text('图书名称:')TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })}Row() {Text('图书作者:')TextInput({ placeholder: '请输入作者名字', text: $$this.author })}Row() {Text('图书出版社:')TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })}Button({ type: ButtonType.Normal }) {Text('保存').fontColor(Color.White).fontWeight(800)}.width('100%').height(40).borderRadius(8).onClick(() => {this.addBook()})}.height('100%').width('100%').padding(10)}.title('新增图书').titleMode(NavigationTitleMode.Mini)}
}
5.3. 删除图书
import axios, { AxiosResponse } from '@ohos/axios'
import { iBookInfo, iBookResponse } from './models'
import { promptAction, router } from '@kit.ArkUI'const req = axios.create()@Entry
@Component
struct Index {@State bookList: iBookInfo[] = []onPageShow(): void {this.getBookList()}async getBookList() {try {let res: AxiosResponse<iBookResponse> =await req.request({url: 'https://hmajax.itheima.net/api/books',params: {creator: 'ivan'}})this.bookList = res.data.data} catch (err) {AlertDialog.show({ message: JSON.stringify(err, null, 2) })}}build() {Column() {// 1. 我的书架this.MyBook()// 2. 书籍列表this.BookList()}.height('100%').width('100%')}// 1. 我的书架@BuilderMyBook() {Row() {Image($r('app.media.ic_public_drawer_filled')).height(20)Text('我的书架').fontSize(20).fontWeight(800)Image($r('app.media.ic_public_add')).height(20).onClick(() => {router.pushUrl({ url: 'pages/axiosbooks/addBook' })})}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding(10).border({ width: { bottom: 1 }, color: { bottom: 'rgba(0,0,0,0.2)' } })}// 2. 书籍列表@BuilderBookList() {List() {ForEach(this.bookList, (item: iBookInfo) => {ListItem() {// 布局Row({ space: 10 }) {Image($r('app.media.ic_public_cover')).width(100)Column({ space: 25 }) {Column() {Text('书名:' + item.bookname).width('100%').fontSize(20).fontWeight(800)Text('作者:' + item.author).width('100%').fontSize(14).fontWeight(600).fontColor('rgba(0,0,0,0.4)').padding({ top: 5 })}Text('出版社:' + item.publisher).width('100%').fontWeight(600).fontColor('rgba(0,0,0,0.4)')}.layoutWeight(1)}.padding(10).onClick(() => {router.pushUrl({ url: 'pages/axiosbooks/editBook', params: { bookid: item.id } })})}.swipeAction({end: this.delBuilder(item.id)})})}}// 3. 删除书籍的构建函数@BuilderdelBuilder(id: number) {Column() {Text('删除').backgroundColor(Color.Red).fontColor(Color.White).height('100%').width(60).textAlign(TextAlign.Center)}.padding(10).onClick(() => {promptAction.showDialog({title: '删除提示',message: '确认删除图书吗?',buttons: [{text: '取消',color: '#000'},{text: '确认',color: '#ff27a1d7'},]}).then(async res => {// res返回的内容:{index:0} 取消按钮被点击, {index:1} 确认按钮被点击// AlertDialog.show({ message: JSON.stringify(res, null, 2) })if (res.index == 1) {try {// 此处编写代码let res: AxiosResponse<iBookResponse> = await req.request({method: 'delete',url: 'https://hmajax.itheima.net/api/books/' + id})promptAction.showToast({ message: res.data.message })this.getBookList()} catch (err) {AlertDialog.show({ message: JSON.stringify(err, null, 2) })}}})})}
}
5.4. 编辑图书
5.4.1. 回显图书信息
// 导入创建者
import { creator, iBookInfoDetial } from './models'
import { router } from '@kit.ArkUI'
import axios, { AxiosResponse } from '@ohos/axios'interface iRouterParams {bookid: number
}const req = axios.create()@Entry
@Component
struct addPage {@State bookname: string = ''@State author: string = ''@State publisher: string = ''bookid: number = 0aboutToAppear(): void {let routerObj = router.getParams() as iRouterParamsthis.bookid = routerObj.bookidthis.loadBook()}// 1. 回显图书数据async loadBook() {try {// 此处编写代码let res: AxiosResponse<iBookInfoDetial> = await req.request({url: 'https://hmajax.itheima.net/api/books/' + this.bookid})this.bookname = res.data.data.booknamethis.author = res.data.data.authorthis.publisher = res.data.data.publisher} catch (err) {console.error('err--->', JSON.stringify(err).slice(0,800))}}build() {Navigation() {Column({ space: 10 }) {Row() {Text('图书名称:')TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })}Row() {Text('图书作者:')TextInput({ placeholder: '请输入作者名字', text: $$this.author })}Row() {Text('图书出版社:')TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })}Button({ type: ButtonType.Normal }) {Text('保存').fontColor(Color.White).fontWeight(800)}.width('100%').height(40).borderRadius(8)}.height('100%').width('100%').padding(10)}.title('编辑 图书').titleMode(NavigationTitleMode.Mini)}
}
5.4.2. 修改图书信息
// 导入创建者
import { creator, iBookInfoDetial } from './models'
import { promptAction, router } from '@kit.ArkUI'
import axios, { AxiosResponse } from '@ohos/axios'
import { iReqeustBody } from './addBook'interface iRouterParams {bookid: number
}const req = axios.create()@Entry
@Component
struct addPage {@State bookname: string = ''@State author: string = ''@State publisher: string = ''bookid: number = 0aboutToAppear(): void {let routerObj = router.getParams() as iRouterParamsthis.bookid = routerObj.bookidthis.loadBook()}// 1. 回显图书数据async loadBook() {try {// 此处编写代码let res: AxiosResponse<iBookInfoDetial> = await req.request({url: 'https://hmajax.itheima.net/api/books/' + this.bookid})this.bookname = res.data.data.booknamethis.author = res.data.data.authorthis.publisher = res.data.data.publisher} catch (err) {console.error('err--->', JSON.stringify(err).slice(0, 800))}}// 2. 修改图书async saveBook() {try {// 此处编写代码let res: AxiosResponse<iBookInfoDetial> =await req.request<null, AxiosResponse<iBookInfoDetial>, iReqeustBody>({method: 'put',url: 'https://hmajax.itheima.net/api/books/' + this.bookid,data: {bookname: this.bookname,author: this.author,publisher: this.publisher,creator: creator}})promptAction.showToast({ message: res.data.message })router.back()} catch (err) {// console.log('编辑图书失败--->', JSON.stringify(err).slice(0, 800))AlertDialog.show({message:JSON.stringify(err,null,2)})}}build() {Navigation() {Column({ space: 10 }) {Row() {Text('图书名称:')TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })}Row() {Text('图书作者:')TextInput({ placeholder: '请输入作者名字', text: $$this.author })}Row() {Text('图书出版社:')TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })}Button({ type: ButtonType.Normal }) {Text('保存').fontColor(Color.White).fontWeight(800)}.width('100%').height(40).borderRadius(8).onClick(()=>{this.saveBook()})}.height('100%').width('100%').padding(10)}.title('编辑 图书').titleMode(NavigationTitleMode.Mini)}
}
相关文章:
1. HTTP 数据请求
相关资源: 图片素材📎图片素材.zip 接口文档 1. HTTP 数据请求 什么是HTTP数据请求: (鸿蒙)应用软件可以通过(鸿蒙)系统内置的 http 模块 和 Axios,通过 HTTP 协议和服务器进行通讯 学习核心Http请求技术: Http模块 - 属于鸿…...
基于深度学习+NLP豆瓣电影数据爬虫可视化推荐系统
博主介绍:资深开发工程师,从事互联网行业多年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有…...
Apache Spark中的依赖关系与任务调度机制解析
Apache Spark中的依赖关系与任务调度机制解析 在Spark的分布式计算框架中,RDD(弹性分布式数据集)的依赖关系是理解任务调度、性能优化及容错机制的关键。宽依赖(Wide Dependency)与窄依赖(Narrow Dependency)作为两种核心依赖类型,直接影响Stage划分、Shuffle操作及容…...
SEO炼金术(4)| Next.js SEO 全攻略
在上一篇文章 SEO炼金术(3)| 深入解析 SEO 关键要素 中,我们深入解析了 SEO 关键要素,包括 meta 标签、robots.txt、canonical、sitemap.xml 和 hreflang,并探讨了它们在搜索引擎优化(SEO)中的作…...
DeepSeek开源周,第五弹再次来袭,3FS
Fire-Flyer 文件系统(3FS)总结: 一、核心特点 3FS 是一个专为 AI 训练和推理工作负载设计的高性能分布式文件系统,利用现代 SSD 和 RDMA 网络,提供共享存储层,简化分布式应用开发。其主要特点包括…...
conda怎么迁移之前下载的环境包,把python从3.9升级到3.10
克隆旧环境(保留旧环境作为备份) conda create -n cloned_env --clone old_env 在克隆环境中直接升级 Python conda activate cloned_env conda install python3.10 升级 Python 后出现 所有包导入失败 的问题,通常是因为依赖包与新 Pyth…...
一周一个Unity小游戏2D反弹球游戏 - 移动的弹板(鼠标版)
前言 本文将实现控制弹板移动,通过Unity的New Input System,可以支持鼠标移动弹板跟随移动,触控点击跟随移动,并且当弹板移动到边界时,弹板不会移动超过边界之外。 创建移动相关的InputAction 项目模版创建的时候默认会…...
wordpress子分类调用父分类名称和链接的3种方法
专为导航而生,在wordpress模板制作过程中常常会在做breadcrumbs导航时会用到,子分类调用父分类的名称和链接,下面这段简洁的代码,可以完美解决这个问题。 <?php echo get_category_parents( $cat, true, » ); ?…...
使用mermaid查看cursor程序生成的流程图
一、得到cursor生成的流程图文本 cursor写的程序正常运行后,在对话框输入框中输入诸如“请生成扫雷的代码流程图”,然后cursor就把流程图给生成了,但是看到的还是文本的样子,保留这部分内容待用 二、注册一个Mermaid绘图账号 …...
GC垃圾回收介绍及GC算法详解
目录 引言 GC的作用域 什么是垃圾回收? 常见的GC算法 1.引用计数法 2.复制算法 3.标记清除 4.标记整理 小总结 5.分代收集算法 ps:可达性分析算法? 可达性分析的作用 可达性分析与垃圾回收算法的关系 结论 引言 在编程世界中,…...
设计后端返回给前端的返回体
目录 1、为什么要设计返回体? 2、返回体包含哪些内容(如何设计)? 举例 3、总结 1、为什么要设计返回体? 在设计后端返回给前端的返回体时,通常需要遵循一定的规范,以确保前后端交互的清晰性…...
Pytorch为什么 nn.CrossEntropyLoss = LogSoftmax + nn.NLLLoss?
为什么 nn.CrossEntropyLoss LogSoftmax nn.NLLLoss? 在使用 PyTorch 时,我们经常听说 nn.CrossEntropyLoss 是 LogSoftmax 和 nn.NLLLoss 的组合。这句话听起来简单,但背后到底是怎么回事?为什么这两个分开的功能加起来就等于…...
Linux实操——在服务器上直接从百度网盘下载(/上传)文件
Linux Linux实操——在服务器上直接从百度网盘下载(/上传)文件 文章目录 Linux前言一、下载并安装bypy工具二、认证并授权网盘账号三、将所需文件转移至目的文件夹下四、下载文件五、上传文件六、更换绑定的百度云盘账户 前言 最近收到一批很大的数据&…...
【无标题】ABP更换MySql数据库
原因:ABP默认使用的数据库是sqlServer,本地没有安装sqlServer,安装的是mysql,需要更换数据库 ABP版本:9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集,可以看到默认使用的是sqlServer&…...
nuxt常用组件库html-validator应用解析
html-validator 主要用于自动验证nuxt服务器呈现的HTML(SSR和SSG),以检测可能导致水合错误的HTML常见问题,有助于减少水合错误,检测常见的可访问性错误。 安装 npx nuxilatest module add html-validator配置 若自动更新nuxt.config.ts配置文…...
思维训练(算法+技巧)
1.深度优先搜索:暴力求解,适合判断能不能走出迷宫 利用递归,有一个check【】数组来检查该节点是否经过 for循环该节点的邻接节点(存在且没被访问),递归DFS(该节点的某个邻接节点) D…...
AIGC(生成式AI)试用 25 -- 跟着清华教程学习 - DeepSeek+DeepResearch让科研像聊天一样简单
目标:继续学习,以DeepSeek为主 个人理解: - 模型结合,充分发挥各模型的优势 - 关注应用,弱化理论,了解就好 - 多模态:多模态(Multimodality)是指结合多种不同类型的数据…...
Solr中得Core和Collection的作用和关系
Solr中得Core和Collection的作用和关系 一, 总结 在Apache Solr中,Core和Collection 是两个核心概念,他们分别用于单机模式和分布式模式(SolrCloud)中,用于管理和组织数据。 二,Core 定义&am…...
温湿度监控设备融入智慧物联网
当医院的温湿度监控设备融入智慧物联网,将会带来许多新的体验,可以帮助医院温湿度监控设备智能化管理,实现设备之间的互联互通,方便医院对温湿度数据进行统一管理和分析。 添加智慧物联网技术,实现对医院温湿度的实时…...
软件测试的七大误区
随着软件测试对提高软件质量重要性的不断提高,软件测试也不断受到重视。但是,国内软件测试过程的不规范,重视开发和轻视测试的现象依旧存在。因此,对于软件测试的重要性、测试方法和测试过程等方面都存在很多不恰当的认识…...
Mac 版 本地部署deepseek ➕ RAGflow 知识库搭建流程分享(附问题解决方法)
安装: 1、首先按照此视频的流程一步一步进行安装:(macos版)ragflowdeepseek 私域知识库搭建流程分享_哔哩哔哩_bilibili 2、RAGflow 官网文档指南:https://ragflow.io 3、RAGflow 下载地址:https://github.com/infi…...
标记符号“<”和“>”符号被称为“尖括号”或“角括号”
你提到的“<”和“>”符号被称为“尖括号”或“角括号”。它们常用于编程语言中表示类型参数(如泛型)、HTML标签(如<div>)、数学中的不等式(如< 5)等。 好的,我来用通俗的方式解…...
DMA发送全部历史记录数据到串口
背景 博主参与的项目中,有个读取全部历史记录的功能,如果下位机在主程序中将全部历史记录单纯地通过串口传输会比较占用cpu资源,影响主程序中别的功能。最后商量得出以下实现方案: 定义两个发送缓冲区DMATxbuf1和DMATxbuf2&…...
js基础案例
1.弹出警告框,显示Hello JS 2.在页面输出内容(内容在body标签里面) 3.在控制台输出内容 4.js代码是自上而下执行 5.将js代码编写到标签的onclick属性中,当点击时,js代码才会执行 6.将js写到超链接的href属性中…...
机器学习之集成学习思维导图
学习笔记—机器学习-集成学习思维导图 20250227,以后复习看(周老师的集成学习) PS:图片看不清,可以下载下来看。 往期思维导图: 机器学习之集成学习Bagging(随机深林、VR-树、极端随机树&…...
学生考勤请假管理系统
在当今信息化时代,传统的纸质考勤和请假管理方式已难以满足高校日益增长的管理需求。手工记录效率低下、容易出错,且难以进行数据统计和分析,无法为教学管理提供有效的决策支持。因此,开发一套高效、便捷、安全的学生考勤请假管理…...
算法之领域算法
领域算法 ♥一些领域算法知识体系♥ | Java 全栈知识体系...
服务 ‘Sql Server VSS writer‘ (SQLWriter) 在安装 LocalDB 时无法启动
安装Microsoft Visual C 2015-2019 Redistributable (x64)...
GDidees CMS v3.9.1本地文件泄露漏洞(CVE-2023-27179)
漏洞简介: GDidees CMS v3.9.1及更低版本被发现存在本地文件泄露漏洞,漏洞通过位于 /_admin/imgdownload.php 的 filename 参数进行利用。 漏洞环境: 春秋云镜中的漏洞靶标,CVE编号为CVE-2023-27179 漏洞复现: 进入靶场发现没…...
PyQT(PySide)的上下文菜单策略设置setContextMenuPolicy()
在 Qt 中,QWidget 类提供了几种不同的上下文菜单策略,这些策略通过 Qt::ContextMenuPolicy 枚举类型来定义,用于控制控件(如按钮、文本框等)在用户右键点击时如何显示上下文菜单。 以下是 Qt::ContextMenuPolicy 枚举中…...
【AI深度学习基础】NumPy完全指南进阶篇:核心功能与工程实践(含完整代码)
NumPy系列文章 入门篇进阶篇终极篇 一、引言 在掌握NumPy基础操作后,开发者常面临真实工程场景中的三大挑战:如何优雅地处理高维数据交互?如何在大规模计算中实现内存与性能的平衡?怎样与深度学习框架实现高效协同?…...
爬虫获取微店商品快递费 item_feeAPI 接口的完整指南
在电商运营中,快递费用的计算是影响用户体验和商家成本的重要因素。通过获取快递费数据,商家可以优化定价策略、提升用户体验,甚至实现个性化的营销方案。本文将详细介绍如何通过爬虫技术调用微店的快递费 API 接口,获取商品的快递…...
etcd 3.15 三节点集群管理指南
本文档旨在提供 etcd 3.15 版本的三节点集群管理指南,涵盖节点的新增、删除、状态检查、数据库备份和恢复等操作。 1. 环境准备 1.1 系统要求 操作系统:Linux(推荐 Ubuntu 18.04 或 CentOS 7) 内存:至少 2GB 磁盘&a…...
Python 数据可视化(一)熟悉Matplotlib
目录 一、安装包 二、先画个折线图 1、修改标签文字和线条粗细 2、内置样式 3、scatter() 绘制散点图 4、scatter() 绘制多个点 5、设置样式 6、保存绘图 数据可视化指的是通过可视化表示来探索和呈现数据集内的规律。 一、安装包 win R 打开终端 安装 Matplotlib&…...
使用自动化运维工具 Ansible 集中化管理服务器
一、概述 Ansible 是一款为类 Unix 系统开发的自由开源的配置和自动化工具 官方网站:https://www.ansible.com/ Ansible 成立于 2013 年,总部设在北卡罗来纳州达勒姆,联合创始人 ad Ziouani 和高级副总裁 Todd Barr都是红帽的老员工。Ansible 旗下的开源软件 Ansible 十分…...
STL 算法库中的 min_element 和 max_element
在 C STL中,min_element 和 max_element 是两个非常实用的算法函数,用于快速找到容器或范围内的最小值和最大值,这里以min为例。 头文件:<algorithm> 语法: template <class ForwardIterator> ForwardIt…...
YOLOv11-ultralytics-8.3.67部分代码阅读笔记-ops.py
ops.py ultralytics\models\utils\ops.py 目录 ops.py 1.所需的库和模块 2.class HungarianMatcher(nn.Module): 3.def get_cdn_group(batch, num_classes, num_queries, class_embed, num_dn100, cls_noise_ratio0.5, box_noise_scale1.0, trainingFalse): 1.所需的库…...
翻译: 深入分析LLMs like ChatGPT 一
大家好,我想做这个视频已经有一段时间了。这是一个全面但面向普通观众的介绍,介绍像ChatGPT这样的大型语言模型。我希望通过这个视频让大家对这种工具的工作原理有一些概念性的理解。 首先,我们来谈谈你在这个文本框里输入内容并点击回车后背…...
【1162. 地图分析 中等】
题目: 你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该…...
PyQT6是干啥的?
PyQt6 是一个用于创建图形用户界面(GUI)的 Python 库,基于 Qt 框架。它允许开发者用 Python 编写跨平台的桌面应用程序,支持 Windows、macOS 和 Linux 等操作系统。 主要功能 GUI 开发:提供丰富的控件(如按…...
华为云之使用鲲鹏弹性云服务器部署Node.js环境【玩转华为云】
华为云之使用鲲鹏弹性云服务器部署Node.js环境【玩转华为云】 一、本次实践介绍1.1 实践环境简介1.3 本次实践完成目标 二、 相关服务介绍2.1 华为云ECS云服务器介绍2.2 Node.js介绍 三、环境准备工作3.1 预置实验环境3.2 查看预置环境信息 四、登录华为云4.1 登录华为云4.2 查…...
PyCharm怎么集成DeepSeek
PyCharm怎么集成DeepSeek 在PyCharm中集成DeepSeek等大语言模型(LLM)可以借助一些插件或通过代码调用API的方式实现,以下为你详细介绍两种方法: 方法一:使用JetBrains AI插件(若支持DeepSeek) JetBrains推出了AI插件来集成大语言模型,不过截至2024年7月,官方插件主要…...
NFC拉起微信小程序申请URL scheme 汇总
NFC拉起微信小程序,需要在微信小程序开发里边申请 URL scheme ,审核通过后才可以使用NFC标签碰一碰拉起微信小程序 有不少人被难住了,从微信小程序开发社区汇总了以下信息,供大家参考 第一,NFC标签打开小程序 https://…...
使用Docker方式一键部署MySQL和Redis数据库详解
一、前言 数据库是现代应用开发中不可或缺的一部分,MySQL和Redis作为两种广泛使用的数据库系统,分别用于关系型数据库和键值存储。本文旨在通过Docker和Docker Compose的方式,提供一个简洁明了的一键部署方案,确保数据库服务的稳…...
spring注解开发(Spring整合MyBatis——Mapper代理开发模式、(Spring、MyBatis、Jdbc)配置类)(6)
目录 一、纯MyBatis独立开发程序。 (1)数据库与数据表。 (2)实体类。 (3)dao层接口。(Mapper代理模式、无SQL映射文件——注解配置映射关系) (4)MyBatis核心配…...
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
Redisson 是一个高性能的 Java Redis 客户端,提供了丰富的分布式工具集,如分布式锁、Map、Queue 等,帮助开发者简化 Redis 的操作。在集成 Redisson 到项目时,开发者通常有两种选择: 使用 Redisson 原始依赖。使用 Re…...
Maven中一些基础知识点
早些时候只知道创建或者开发springboot项目时候,有一个叫pom.xml的文件可以用来管理项目所需的依赖/第三方工具。 索性稍微深入了解了一下,然后把自己认为重要的记录下来。 首先我们要引入新的依赖自然是在dependencies下写dependency,这个…...
塑造网络安全的关键事件
注:本文为 “网络安全” 相关文章合辑。 机翻,未校。 Timeline of Cyber Security: Key Events that Shaped the Field 网络安全时间表:塑造该领域的关键事件 October 29, 2023 Cyberattacks are an everyday threat, always changing. T…...
前端项目打包生成 JS 文件的核心步骤
前端项目打包生成 JS 文件的过程通常涉及以下核心步骤,以主流工具(如 Webpack、Vite、Rollup 等)为例: 一、项目准备阶段 项目结构 源代码目录(如 src/)包含 JS/TS、CSS、图片等资源配置文件(pa…...
【Pandas】pandas Series fillna
Pandas2.2 Series Computations descriptive stats 方法描述Series.backfill(*[, axis, inplace, limit, …])用于填充 Series 中缺失值(NaN)的方法Series.bfill(*[, axis, inplace, limit, …])用于填充 Series 中缺失值(NaN)的…...