当前位置: 首页 > news >正文

从 AJAX 到 axios:前端与服务器通信实战指南

直到现在我们小宁已经更新了44作品了,其中和大家介绍了Python入门基础、Fast API框架、SQLite数据库,以及前端的知识都已经学习完了,总的来说现在前端、后端、数据库已经都学习了,那大家是否有这样的疑问,前端后端到底应该怎么联系起来使用呢?

在现代 Web 开发中,网页不再是静态的信息展示板,而是能与服务器实时交互的动态应用。实现这一功能的核心技术就是 AJAX,而 axios 则是简化 AJAX 操作的利器。本文从基础概念到实战案例,带你掌握前端与服务器通信的全流程。

一、认识 AJAX:让数据 “动” 起来

1. 什么是 AJAX?

AJAX(Asynchronous JavaScript and XML)是一种通过浏览器的 XMLHttpRequest 对象与服务器异步通信的技术。它能让网页在不刷新的情况下,向服务器请求数据并更新页面内容。

例如,当你在网页上点击 “查询省份” 按钮时,浏览器通过 AJAX 向服务器发送请求,服务器返回省份列表数据,前端直接将数据展示在页面上,整个过程无需刷新页面。

2. 为什么需要 AJAX?

传统网页的数据是固定写在代码中的,无法实时更新。有了 AJAX,数据可以从服务器动态获取,让页面内容 “活” 起来。比如:实时显示最新的省份 / 城市列表、用户登录状态验证等。

3. 为什么选择 axios?

AJAX 底层依赖 XMLHttpRequest 对象,但语法繁琐。axios 是一个基于 Promise 的 HTTP 客户端,语法简洁,且在 Vue 等框架中被广泛使用,能让我们更专注于业务逻辑而非底层通信细节。

二、URL:定位服务器资源的 “地址”

要与服务器通信,首先需要知道资源的位置 ——URL(统一资源定位符)。

1. URL 的核心组成

一个完整的 URL 包含三个关键部分:

  • 协议:如 http://,规定浏览器与服务器的通信规则;
  • 域名 / IP:如 127.0.0.1:8000,标记服务器在网络中的位置;
  • 资源路径:如 /api/province,指定服务器上具体资源的位置。

例如,http://127.0.0.1:8000/api/province 表示:通过 HTTP 协议,访问本地服务器(127.0.0.1:8000)上的省份列表资源。

2. axios 中携带查询参数

在 axios 中,通过 params 选项设置查询参数,无需手动拼接 URL:

// 获取辽宁省的城市列表
axios({url: 'http://127.0.0.1:8000/api/city',params: {pname: '辽宁省' // 参数名与服务器要求一致(课件中服务器约定参数名为pname)}
}).then(result => {// 服务器返回的数据格式为 { list: [城市1, 城市2, ...] }console.log('辽宁省城市列表:', result.data.list); // 渲染到页面:将城市列表转为li标签document.querySelector('ul').innerHTML = result.data.list.map(city => `<li>${city}</li>`).join('');
});

三、请求方法和常见报错:与服务器的 “交互方式”

HTTP 协议定义了多种请求方法,用于表示对服务器资源的操作。常用方法如下:

请求方法作用示例
GET获取资源(如查询数据)查询省份列表
POST提交数据(如注册、登录)用户注册
PUT全量更新资源修改用户所有信息
DELETE删除资源删除一条记录

HTTP 常见响应状态码(错误码)说明

状态码类别含义说明常见场景示例
200成功请求成功,服务器正常返回数据登录成功、查询数据成功
400客户端错误请求参数错误或格式不正确用户名不符合规则(如长度不足)
401客户端错误未授权,需要验证身份(如登录失效)密码错误、未登录访问需要权限的资源
404客户端错误请求的资源不存在访问了错误的 URL(如 /api/xxx 拼写错误)
500服务器错误服务器内部出错,无法处理请求服务器代码报错、数据库连接失败
403客户端错误服务器拒绝请求(如权限不足)普通用户尝试删除管理员数据
408客户端错误请求超时网络延迟导致服务器未及时收到请求
503服务器错误服务器暂时不可用(如维护中)服务器负载过高、正在重启

四、综合案例

1、axios的使用步骤

①引入axios.js文件到自己的网页中:axios 在线引入地址(复制直接使用)

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script>

明确axios函数的使⽤语法

综合语句1:
axios({// 配置项url: '目标地址',method: '请求方法', // 默认为 getparams: {}, // GET 参数data: {}    // POST 参数
})
.then(result => {// 成功回调:处理服务器返回的数据
})
.catch(error => {// 失败回调:处理错误信息
});综合语句2:
axios.请求方法(url:'目标地址',{参数名1:值1;.......
}).then(result => {// 成功回调:处理服务器返回的数据
})
.catch(error => {// 失败回调:处理错误信息
});

2、综合案例代码

 province_API.py:这里有后续网页对应的API接口

from fastapi import FastAPI
# 浏览器出于安全考虑,默认会阻止跨域请求(例如前端运行在 http://localhost:3000,
# 而 API 服务在 http://localhost:8000),这时就需要后端设置 CORS 来允许跨域访问。
from fastapi.middleware.cors import CORSMiddleware
# 用于创建数据库引擎,常用于同步数据库连接
from sqlalchemy import create_engine,Column,Integer,String
# 用于创建数据库会话,用于执行数据库操作
from sqlalchemy.orm import sessionmaker, declarative_base# 创建FastAPI应用
app = FastAPI()# 添加CORS中间件,允许跨域传输
app.add_middleware(CORSMiddleware,allow_origins=["*"],  # 允许所有源allow_credentials=True,  # 是否允许发送 Cookieallow_methods=["*"],  # 允许所有HTTP方法allow_headers=["*"],  # 允许所有HTTP头部
)
# 定义数据库连接URL
DATABASE_URL = "sqlite:///province.db"
# 创建数据库引擎,设置连接参数以允许在多线程环境中使用(地址)
engine = create_engine(DATABASE_URL,connect_args={"check_same_thread": False})
# 创建会话,绑定数据库引擎
SessionLocal = sessionmaker(bind=engine)
# 创建基类
Base = declarative_base()
# 创建数据库表结构(可以创建数据库表结构)
class Province(Base):__tablename__ = "province"code = Column(String)id = Column(Integer, primary_key=True, index=True)name = Column(String, unique=True, index=True)
# 执行创建数据库表结构
Base.metadata.create_all(bind = engine)@app.get("/api/all_province")
def get_all_provinces():"""获取所有省份列表返回格式与前端期望的格式一致,包含list属性"""db = SessionLocal()try:provinces = db.query(Province).all()province_list = [province.name for province in provinces]return {"list": province_list}finally:db.close()@app.get("/api/find_province")
def find_province(name: str):"""根据名称查询省份返回格式与前端期望的格式一致,包含list属性"""db = SessionLocal()try:find_province = db.query(Province).filter(Province.name == name).first()if find_province:return find_province.namereturn "未找到该省份"finally:db.close()# 实现城市查询API接口
@app.get("/api/city")
def get_cities(pname: str = None):"""根据省份名称获取城市列表参数:- pname: 省份名称"""# 这里简化处理,实际应该查询数据库中的城市数据# 为演示目的,返回一些示例城市cities = {"辽宁省": ["沈阳市", "⼤连市", "鞍⼭市", "抚顺市", "本溪市"],"上海": ["上海市"],"⼴东省": ["⼴州市", "深圳市", "珠海市", "汕头市", "佛⼭市"],"北京": ["北京", "东城", "西城", "朝阳", "海淀", "丰台", "石景山", "门头沟", "房山", "通州", "顺义", "昌平"],"天津": ["天津", "和平", "河北", "河东", "河西", "南开", "河北", "和平", "宁河", "东丽", "西青", "津南", "北辰"],}if pname and pname in cities:return {"list": cities[pname]}return {"list": []}
# 实现地区查询API接口
@app.get("/api/area")
def get_areas(cname: str = None):"""根据省份和城市名称获取地区列表参数:- pname: 省份名称- cname: 城市名称"""# 这里简化处理,实际应该查询数据库中的地区数据# 为演示目的,返回一些示例地区areas = {"北京市": ["东城区", "西城区", "朝阳区", "海淀区", "丰台区", "石景山区"],"上海市": ["黄浦区", "徐汇区", "长宁区", "静安区", "普陀区", "虹口区"],"广州市": ["越秀区", "荔湾区", "海珠区", "天河区", "白云区", "黄埔区"],"深圳市": ["福田区", "罗湖区", "南山区", "宝安区", "龙岗区", "盐田区"]}if cname and cname in areas:return {"list": areas[cname]}return {"list": []}if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8080)

data.py:主要用于创建数据库,插入数据库的省份数据

import sqlite3
# 创建数据库连接
conn = sqlite3.connect('province.db')
# 创建数据库游标:游标能够对数据库进行操作
cursor = conn.cursor()
# 创建表
sql = '''
CREATE TABLE IF NOT EXISTS province (id INTEGER PRIMARY KEY,name TEXT NOT NULL,code TEXT NOT NULL
)'''
cursor.execute(sql)
sql = '''
insert into province(name,code)values
('北京', '110000'),
('天津', '120000'),
('河北', '130000'),
('⼭⻄', '140000'),
('内蒙古', '150000'),
('辽宁', '210000'),
('吉林', '220000'),
('⿊⻰江', '230000'),
('上海', '310000'),
('江苏', '320000'),
('浙江', '330000'),
('安徽', '340000'),
('福建', '350000'),
('江⻄', '360000')
'''
cursor.execute(sql)
conn.commit()
conn.close()

 all_province.html:这个页面主要是对应 province_API里面的第一个接口,使用get的请求方式,不带参数来获取数据库的所有省份信息

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>所有的省份信息</title>
</head>
<body><h1>这里是所有的省份信息</h1><p id="all_province"></p><script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script><script>axios({url: 'http://127.0.0.1:8080/api/all_province'}).then(result => {// 对服务器返回的数据做后续处理console.log(result)console.log(result.data)console.log(result.data.list)let all_province = document.getElementById('all_province')all_province.innerHTML = result.data.list.join('<br/>')})</script><p></p>
</body>
</html>

 

find_city.html:这个页面主要是对应 province_API里面的第二个接口,使用post的请求方式,带查询城市名称参数来获取地区信息
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>显示城市的各个区</title>
</head>
<body><h1>显示城市的各个区</h1>城市:<input type="text" id="input" placeholder="请输入你要查找的城市"><button id = "btn">查找</button><h2>以下是查找的结果:</h2>省份:<p id="sf"></p>区:<p id="city"></p><script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script><script>let input = document.getElementById('input');let btn = document.getElementById('btn');let sf = document.getElementById('sf');let city = document.getElementById('city');btn.addEventListener('click', function () {if (input.value) {axios({url: 'http://127.0.0.1:8080/api/city',params: {pname: input.value}}).then(result => {// 对服务器返回的数据做后续处理// console.log(result)// console.log(result.data)console.log(result.data.list)if (result.data.list.length != 0){sf.innerHTML = input.valuecity.innerHTML = result.data.list.join('<br/>')}else {sf.innerHTML = '没有找到该城市'}})}})</script>
</body>
</html>

 

find_area.html:这个页面主要是对应 province_API里面的第三个接口,使用post的请求方式,带查询城市名称参数来获取地区信息
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>查找地区列表</title><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>案例_地区查询</title>
</head>
<body><h1>显示城市的各个区</h1>城市:<input type="text" id="input" placeholder="请输入你要查找的城市"><button id = "btn">查找</button><h2>以下是查找的结果:</h2>城市:<p id="sf"></p>区:<p id="city"></p><script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script><script>const input = document.getElementById('input');const btn = document.getElementById('btn');const sf = document.getElementById('sf');const city = document.getElementById('city');btn.addEventListener('click', function () {if (input.value) {axios({url: 'http://127.0.0.1:8080/api/area',params: {cname: input.value}}).then(result => {// 对服务器返回的数据做后续处理// console.log(result)// console.log(result.data)console.log(result.data.list)if (result.data.list.length != 0){sf.innerHTML = input.valuecity.innerHTML = result.data.list.join('\n')}else {sf.innerHTML = '没有找到该城市'}})}})</script>
</body>
</html>

find_province.html:这个页面主要是对应 province_API里面的第四个接口,使用post的请求方式,带查询数据库中是否存在该城市
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>查找城市是否存在</title>
</head>
<body><input type="text" id="input"><button id="btn">查找</button><p id="find_province"></p><script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script><script>let input = document.getElementById('input');let btn = document.getElementById('btn');let find_province = document.getElementById('find_province');btn.addEventListener('click', function () {if (input.value) {axios({url: 'http://127.0.0.1:8080/api/find_province',params: {name: input.value}}).then(result => {// 对服务器返回的数据做后续处理console.log(result)console.log(result.data)find_province.innerText = result.data})}})</script>
</body>
</html>

五、综合案例 2:用户登录(结合 form-serialize)

需求:实现用户登录功能,包含表单验证、数据提交和结果提示,并使用 form-serialize 插件简化表单数据收集。

1. form-serialize 插件介绍

1. 我们前⾯收集表单元素的值,是⼀个个标签获取的
2. 如果⼀套表单⾥有很多很多表单元素,如何⼀次性快速收集出来呢?
3. 使⽤ form-serialize 插件提供的 serialize 函数就可以办到
4. form-serialize 插件语法:
   
  • 引入插件:<script src="https://unpkg.com/form-serialize@0.7.2/form-serialize.min.js"></script>
  • 调用 serialize 函数:serialize(表单元素, { hash: true, empty: true })hash: true 返回对象,empty: true 包含空值)。
参数1:要获取的 form 表单标签对象(要求表单元素需要有 name 属性-⽤来作为收集的
数据中属性名)
参数2:配置对象
        hash:
                true - 收集出来的是⼀个 JS 对象结构
                false - 收集出来的是⼀个查询字符串格式
        empty:
                true - 收集空值
                false - 不收集空值
5. 需求:收集登录表单⾥⽤户名和密码
   <!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>form-serialize插件使⽤</title></head><body><form action="javascript:;" class="example-form"><input type="text" name="username"><br><input type="text" name="password"><br><input type="button" class="btn" value="提交"></form><!--/2. 使⽤serialize函数,快速收集表单元素的值参数1:要获取哪个表单的数据表单元素设置name属性,值会作为对象的属性名建议name属性的值,最好和接⼝⽂档参数名⼀致参数2:配置对象hash 设置获取数据结构- true:JS对象(推荐)⼀般请求体⾥提交给服务器- false: 查询字符串empty 设置是否获取空值- true: 获取空值(推荐)数据结构和标签结构⼀致- false:不获取空值/--><!-- 引入 serialize.js 插件 --><script src="https://unpkg.com/form-serialize@0.7.2/form-serialize.min.js"></script><script>document.querySelector('.btn').addEventListener('click', () => {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></body></html>


 

http://www.lqws.cn/news/557227.html

相关文章:

  • 2023国赛linux的应急响应-wp
  • Re--攻防世界-基础android
  • C++ vector 完全指南:从入门到精通
  • 源码运行效果图(六)
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(三十八) -> 构建HAR
  • 基于springboot的海产品交易系统
  • 【数据标注师】3D标注
  • JWT认证性能优化实战指南
  • 《从 0 到 1 掌握正则表达式:解析串口数据的万能钥匙》
  • springboot+Vue逍遥大药房管理系统
  • 创建套接字时和填充地址时指定类型的异同
  • C++泛型编程2 - 类模板
  • 【数论】P11169 「CMOI R1」Bismuth / Linear Sieve|普及+
  • 嵌入式硬件与应用篇---寄存器GPIO控制
  • 进阶向:Flask框架详解,从零开始理解Web开发利器
  • Odoo邮箱别名使用指南:从配置到业务流程自动化
  • C# 委托(为委托添加方法和从委托移除方法)
  • docker部署后端服务的脚本
  • Golang JSON 标准库用法详解
  • Foundry测试实战:解锁区块链测试新姿势
  • Java 大视界 -- Java 大数据机器学习模型在金融市场高频交易策略优化与风险控制中的应用(327)
  • 单调栈一文深度解析
  • NLP——文本预处理(下)
  • 翻译服务器
  • Redis高级数据结构深度解析:BitMap、布隆过滤器、HyperLogLog与Geo应用实践
  • 趣味数据结构之——数组
  • Java 使用 Easy Excel 进行 Excel 数据导入导出
  • 一分钟了解思路链提示词(Chain-of-thought Prompting)
  • uni-app manifest.json 配置:定制化应用的各项功能和行为
  • 基于Pandas和FineBI的昆明职位数据分析与可视化实现(二)- 职位数据清洗与预处理