
学习完了前端三件套(HTML、CSS、JavaScript),

在进行框架学习之前,

我们还需要学习一些前置知识,

在当下,我们将初步进行“前后端交互”、感知“前端工程化”;
在未来,它将伴随,并推进,整个的前端框架学习过程;
……
我们继续跟随黑马网课,打下框架学习基础。本次学习的是:


我是Capybara,您的前端学习伙伴,高级网课品鉴官,前端学习测评家
不达目的不放弃,追逐理想的过程本身就难能可贵。

浏览器大家不陌生,服务器可以暂时理解为一台“提供数据”的电脑(一台二十四小时不关机的电脑)。
我们可以在浏览器的网页中使用AJAX相关对应的代码,
运行时,将会发出一次“请求”(让服务器满足我的要求——例如我要一份省份列表数据),
数据不再直接嵌在代码里,而是从服务器返回,
因此称数据“活”起来了。

如何使用AJAX —— 可以使用封装好的axios库

axios语法(使用到promise,后续讲解)

需要使用到网络地址

直接点击网址可在浏览器访问到,返回一个对象结构的json字符串
message是提示信息,list才是省份列表数据

打印返回结果result,result为一个对象,其中data属性为服务器返回真正数据。

我们可以通过result.data.list拿到省份列表数据

获取到数据后,数组转字符串(join方法)并插入换行符(
),
便可展示到元素上

实践代码:
- 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>AJAX概念和axios使用title>
- head>
-
- <body>
-
- <p class="my-p">p>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- // 2. 使用axios函数
- axios({
- url: 'http://hmajax.itheima.net/api/province'
- }).then(result => {
- console.log(result)
- // 好习惯:多打印,确认属性名
- console.log(result.data.list)
- console.log(result.data.list.join('
')) - // 把准备好省份列表,插入到页面
- document.querySelector('.my-p').innerHTML = result.data.list.join('
') - })
- script>
- body>
-
- html>

为什么要认识URL呢?


URL的组成:协议 + 域名 + 资源路径

协议——规定了浏览器和服务器之间传输数据的格式

域名——指出访问的是哪一台服务器电脑

资源路径——标识访问文件在服务器电脑当中的具体位置

尝试获取新闻列表数据



在axios中,查询参数写到params选项中

不同pname,将返回不同数据:
福建省

辽宁省

- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>查询参数title>
- head>
- <body>
-
- <p>p>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- axios({
- url: 'http://hmajax.itheima.net/api/city',
- // 查询参数
- params: {
- pname: '辽宁省'
- }
- }).then(result => {
- console.log(result.data.list)
- document.querySelector('p').innerHTML = result.data.list.join('
') - })
- script>
- body>
- html>
日常常见的功能,比如设置籍贯,可以选择省份,城市,地区,三级选择。
本案例选择省份和城市,展示地区。

要携带多个参数


对象增强写法(ES6):变量名和属性名相同时,可简写
params: {
pname,
cname
}

实践代码:
- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>案例_地区查询title>
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
- <style>
- :root {
- font-size: 15px;
- }
-
- body {
- padding-top: 15px;
- }
- style>
- head>
-
- <body>
- <div class="container">
- <form id="editForm" class="row">
-
- <div class="mb-3 col">
- <label class="form-label">省份名字label>
- <input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" />
- div>
-
- <div class="mb-3 col">
- <label class="form-label">城市名字label>
- <input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" />
- div>
- form>
- <button type="button" class="btn btn-primary sel-btn">查询button>
- <br><br>
- <p>地区列表: p>
- <ul class="list-group">
-
- <li class="list-group-item">东城区li>
- ul>
- div>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- /*
- 获取地区列表: http://hmajax.itheima.net/api/area
- 查询参数:
- pname: 省份或直辖市名字
- cname: 城市名字
- */
- // 目标: 根据省份和城市名字, 查询地区列表
- // 1. 查询按钮-点击事件
- document.querySelector('.sel-btn').addEventListener('click', () => {
- // 2. 获取省份和城市名字
- let pname = document.querySelector('.province').value
- let cname = document.querySelector('.city').value
-
- // 3. 基于axios请求地区列表数据
- axios({
- url: 'http://hmajax.itheima.net/api/area',
- params: {
- pname,
- cname
- }
- }).then(result => {
- // console.log(result)
- // 4. 把数据转li标签插入到页面上
- let list = result.data.list
- console.log(list)
- let theLi = list.map(areaName => `
- ${areaName}
`).join('') - console.log(theLi)
- document.querySelector('.list-group').innerHTML = theLi
- })
- })
-
-
- script>
- body>
-
- html>
前面都是从服务器“拿”(获取)数据,
怎样把数据“存”(提交、保存)到服务器呢?

什么情况需要提交数据?

注意区分:params和data
method不区分大小写,get可以省略,属性值为字符串,记得加上引号

数据提交场景——注册账号

实操代码:
- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>常用请求方法和数据提交title>
- head>
-
- <body>
- <button class="btn">注册用户button>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- /*
- 注册用户:http://hmajax.itheima.net/api/register
- 请求方法:POST
- 参数名:
- username:用户名(中英文和数字组成,最少8位)
- password:密码 (最少6位)
- 目标:点击按钮,通过axios提交用户和密码,完成注册
- */
- document.querySelector('.btn').addEventListener('click', () => {
- axios({
- url: 'http://hmajax.itheima.net/api/register',
- method: 'POST',
- data: {
- username: 'itheima007',
- password: '7654321'
- }
- })
- })
- script>
- body>
-
- html>
重复提交相同数据,会提示账号被占用:

总结

想要把错误信息展示给用户(用户不会去查看控制台)

在axios的then方法后使用catch方法,

当出现axios错误时,控制台一共会出现两段错误信息,
第一段(上面一段)为浏览器报错,它是没有服务器返回的错误原因
不管它

而在下面一段(第二段)是axios捕获(catch)到的错误信息
是一个对象,
在response属性的data属性,有报错原因
我们要取到它,再反馈给用户

通过catch方法捕获错误信息(错误信息传至形参error)
(错误信息不再爆红,之前爆红 显示Uncaught(in pormise),未捕获)

把错误原因取出error.response.data.message
用提示框提示用户alert


报文中有一些自动生成的,
也有一些对应着axios的选项设置,比如post方法,url,
其中Content-Type: application/json规定的是这次请求携带的数据类型
一个空行后面,就是携带的json字符串了
axios在运行时会把代码中的data对象转成json字符串携带到请求报文中。

请求报文的组成部分/格式

自己(程序员)如何查看这些请求信息?——浏览器
发送请求之后,
网络-->fetch/XHR-->选中某一个请求-->标头(看请求头,载荷看请求体)-->点击查看源代码(点击后变成查看解析结果)
部分内容(协议 http://)经浏览器格式化

总结:
报文一共有四个部分:
请求行、请求头、空行、请求体

在登录时,报错“用户名或密码错误”,如何排查错误?

把input框type改成text可以看到密码
查看请求报文,发现所传密码有误

原来是在代码中,获取密码框出现错误

响应报文也分成四部分,
其中响应行中携带HTTP响应状态码

响应状态码表示请求是否成功
关注2和4开头的(200、404)
客户端错误,客户端可以理解为浏览器

通过代码发送请求后,这次要查看的是“响应”标头

响应头(携带额外信息)

响应体

实操代码:
- 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>HTTP协议_响应报文title>
- head>
-
- <body>
- <button class="btn">注册用户button>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- /*
- 注册用户: http://hmajax.itheima.net/api/register
- 请求方法: POST
- 参数名:
- username: 用户名 (中英文和数字组成, 最少8位)
- password: 密码 (最少6位)
- 目标: 点击按钮, 通过axios提交用户和密码, 完成注册
- 需求: 使用axios错误处理语法, 拿到报错信息, 弹框反馈给用户
- */
- document.querySelector('.btn').addEventListener('click', () => {
- axios({
- url: 'http://hmajax.itheima.net/api/registrweer1ddd',
- method: 'post',
- data: {
- username: 'itheima007',
- password: '7654321'
- }
- }).then(result => {
- // 成功
- console.log(result)
- }).catch(error => {
- // 失败
- // 处理错误信息
- // console.log(error)
- console.log(error.response.data.message)
- // alert(error.response.data.message)
- })
- })
- script>
- body>
-
- html>
总结


文档内容与代码相对应

application/json是
后端告诉我们,这一次提交的请求体数据需要json字符串
我们传入的不是data对象吗?
axios源码发现data属性值为对象,内部会把对象转成json字符串,携带给服务器

已注册,实操登录
对照接口文档,填入相关信息:url、请求方法、请求体数据

没有使用then方法捕获,但可以在浏览器中直接查看响应

查看请求载荷(请求体)(需要查看源代码),发现已经转成json字符串。

总结:接口文档是后端提供的描述接口的文章


面对嵌套多层的对象,可以在浏览器中找到需要的属性并右键,选择复制属性路径
error. 然后粘贴

实操代码:
- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>案例_登录title>
-
- <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:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
-
- // 1.1 登录-点击事件
- document.querySelector('.btn-login').addEventListener('click', () => {
- // 1.2 获取用户名和密码
- const username = document.querySelector('.username').value
- const password = document.querySelector('.password').value
- // console.log(username, password)
-
- // 1.3 判断长度
- if (username.length < 8) {
- 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>

使用了bootstrap
警告框(Alert) · Bootstrap v5 中文文档 v5.3 | Bootstrap 中文网

- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>案例_登录_提示消息title>
-
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
-
- <style>
- html,
- body {
- background-color: #EDF0F5;
- width: 100%;
- height: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .container {
- width: 520px;
- height: 540px;
- background-color: #fff;
- padding: 60px;
- box-sizing: border-box;
- }
-
- .container h3 {
- font-weight: 900;
- }
- style>
-
- <style>
- .form_wrap {
- color: #8B929D !important;
- }
-
- .form-text {
- color: #8B929D !important;
- }
- style>
-
- <style>
- .alert {
- transition: .5s;
- opacity: 0;
- }
-
- .alert.show {
- opacity: 1;
- }
- style>
- head>
-
- <body>
- <div class="container">
- <h3>欢迎-登录h3>
-
- <div class="alert alert-success" role="alert">
- 提示消息
- div>
-
- <div class="form_wrap">
- <form>
- <div class="mb-3">
- <label for="username" class="form-label">账号名label>
- <input type="text" class="form-control username">
- div>
- <div class="mb-3">
- <label for="password" class="form-label">密码label>
- <input type="password" class="form-control password">
- div>
- <button type="button" class="btn btn-primary btn-login"> 登 录 button>
- form>
- div>
- div>
- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
- <script>
- // 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
- // 目标2:使用提示框,反馈提示消息
- // 2.1 获取提示框
- const myAlert = document.querySelector('.alert')
- /**
- * 2.2 封装提示框函数,重复调用,满足提示需求
- * 功能:
- * 1. 显示提示框
- * 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
- * 3. 过2秒后,让提示框自动消失
- */
- function alertFn(msg, isSuccess) {
- // 1> 显示提示框
- myAlert.classList.add('show')
-
- // 2> 实现细节
- myAlert.innerText = msg
- const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
- myAlert.classList.add(bgStyle)
-
- // 3> 过2秒隐藏
- setTimeout(() => {
- myAlert.classList.remove('show')
- // 提示:避免类名冲突,重置背景色
- myAlert.classList.remove(bgStyle)
- }, 2000)
- }
-
- // 1.1 登录-点击事件
- document.querySelector('.btn-login').addEventListener('click', () => {
- // 1.2 获取用户名和密码
- const username = document.querySelector('.username').value
- const password = document.querySelector('.password').value
- // console.log(username, password)
-
- // 1.3 判断长度
- if (username.length < 8) {
- alertFn('用户名必须大于等于8位', false)
- console.log('用户名必须大于等于8位')
- return // 阻止代码继续执行
- }
- if (password.length < 6) {
- alertFn('密码必须大于等于6位', false)
- console.log('密码必须大于等于6位')
- return // 阻止代码继续执行
- }
-
- // 1.4 基于axios提交用户名和密码
- // console.log('提交数据到服务器')
- axios({
- url: 'http://hmajax.itheima.net/api/login',
- method: 'POST',
- data: {
- username,
- password
- }
- }).then(result => {
- alertFn(result.data.message, true)
- console.log(result)
- console.log(result.data.message)
- }).catch(error => {
- alertFn(error.response.data.message, false)
- console.log(error)
- console.log(error.response.data.message)
- })
- })
- script>
- body>
-
- html>


打印获取到的表单数据(表单元素的值)
表单元素需要设置name属性,name属性回作为返回对象的属性名

配置对象中的hash属性用于设置获取数据的结构:
为true时,获取数据为JS对象;
为false时,获取数据为查询字符串。
一般使用true,表单获取的数据会被提交到服务器,将被携带在请求体,一般要求传一个对象。

empty属性设置是否获取空值(表单元素的值为空)

如果不获取空值,而表单元素的值均为空,则返回空对象(不是null)

登录案例结合serialize插件
- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>案例_登录_插件使用title>
-
- <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 class="login-form">
- <div class="mb-3">
- <label for="username" class="form-label">账号名label>
- <input type="text" class="form-control username" name="username">
- div>
- <div class="mb-3">
- <label for="password" class="form-label">密码label>
- <input type="password" class="form-control password" name="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 src="./lib/form-serialize.js">script>
- <script>
- // 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
- // 目标2:使用提示框,反馈提示消息
- // 目标3:使用form-serialize插件,收集用户名和密码
-
- // 2.1 获取提示框
- const myAlert = document.querySelector('.alert')
- /**2.2 封装提示框函数,重复调用,满足提示需求
- * 功能:
- * 1. 显示提示框
- * 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
- * 3. 过2秒后,让提示框自动消失
- */
- function alertFn(msg, isSuccess) {
- // 1> 显示提示框
- myAlert.classList.add('show')
-
- // 2> 实现细节
- myAlert.innerText = msg
- const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
- myAlert.classList.add(bgStyle)
-
- // 3> 过2秒隐藏
- setTimeout(() => {
- myAlert.classList.remove('show')
- // 提示:避免类名冲突,重置背景色
- myAlert.classList.remove(bgStyle)
- }, 2000)
- }
-
- // 1.1 登录-点击事件
- document.querySelector('.btn-login').addEventListener('click', () => {
- // 3.2 使用serialize函数,收集登录表单里用户名和密码
- const form = document.querySelector('.login-form')
- const data = serialize(form, { hash: true, empty: true })
- console.log(data)
- // {username: 'itheima007', password: '7654321'}
- const { username, password } = data
-
- // 1.2 获取用户名和密码
- // const username = document.querySelector('.username').value
- // const password = document.querySelector('.password').value
- console.log(username, password)
-
- // 1.3 判断长度
- if (username.length < 8) {
- alertFn('用户名必须大于等于8位', false)
- console.log('用户名必须大于等于8位')
- return // 阻止代码继续执行
- }
- if (password.length < 6) {
- alertFn('密码必须大于等于6位', false)
- console.log('密码必须大于等于6位')
- return // 阻止代码继续执行
- }
-
- // 1.4 基于axios提交用户名和密码
- // console.log('提交数据到服务器')
- axios({
- url: 'http://hmajax.itheima.net/api/login',
- method: 'POST',
- data: {
- username,
- password
- }
- }).then(result => {
- alertFn(result.data.message, true)
- console.log(result)
- console.log(result.data.message)
- }).catch(error => {
- alertFn(error.response.data.message, false)
- console.log(error)
- console.log(error.response.data.message)
- })
- })
- script>
- body>
-
- html>

我是Capybara,期待你的点赞支持。