AJAX-2023.5.2

AJAX-2023.5.2

15209223972

知识回顾

1.html+css 阶段
2.移动web阶段(移动适配、响应式布局、flex、动画)
3.js基础(面试题较多)
4.webapi阶段(DOM、BOM)
5、js高级 (面试题比较多)
6、git
7、项目实战
8、ajax(和服务端进行通信)
9、node学习 (为vue的学习做准备
10、echarts (做大屏开发比较多)
11、大屏的项目实战
12、VUE基础
、、、、、、
知识体系和框架需要建立起来

学习方法

1.预习根据个人情况
2.上课速记(笔记本、txt文档)
3.晚自习作业及笔记梳理 (尝试用自己的白话文去整理)推荐: 云笔记(印象笔记、网易与笔记)

AJAX 概念和 axios 使用

什么是AJAX

AJAX 是异步的 JavaScript和XML (Asynchronous JavaScript And XML) 。简单点说,就是使用XMLHttpRequest 对象与服务器通信。它可以使用JSON,XML,HTML 和 text 文本等格式发送和接收数据。AJAX 最吸引人的就是它的“异步“特性,也就是说它可以在不重新刷新页面的情况下与服务器通信,交换数据,或更新页面。

概念: AJAX 是浏览器与服务器进行数据通信的技术

AJAX-2023.5.2_第1张图片

如何使用AJAX
  • 方式1:可以使用jQuery中封装的ajax $.ajax()

  • 方式2:用axios插件(最常见,后面一直会用)
    AJAX-2023.5.2_第2张图片

<!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>Document</title>
</head>

<body>
    <div class="test">测试</div>
    <button class="btn">查询</button>
    <!-- 第一步:采用CDN在线地址的方式引入axios插件 -->
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
    <script>
        // 点击按钮时通过axios插件发起接口请求,获取服务器的数据
        document.querySelector('.btn').addEventListener('click', function () {
            console.log(1234567)
            axios({
                url: 'http://hmajax.itheima.net/api/province'  //服务地址
            }).then((res) => {
                // res代表的是后台返回的数据
                // console.log(res)
                let list = res.data.list
                console.log(list)
                document.querySelector('.test').innerHTML = list.join('
'
)//利用数组的join方法转换为字符串展示 }) }) </script> </body> </html>

AJAX-2023.5.2_第3张图片

  • 方式3:采用的是最原生的方式 XMLHttpRequest(不常用,是底层,需知道步骤,面试会问)

认识 URL

AJAX-2023.5.2_第4张图片

什么是 URL?

定义:统一资源定位符(英语: Uniform Resource Locator,缩写: URL,或称统一资源定位器、定位地址、URL地址)俗称网页地址,简称网址,是因特网上标准的资源的地址(Address),如同在网络上的门牌。它最初是由蒂姆·伯纳斯-李发明用来作为万维网的地址,现在它已经被万维网联盟编制为因特网标准RFC 1738
AJAX-2023.5.2_第5张图片

概念: URL 就是统一资源定位符,简称网址,用于访问网络上的资源
URL的组成:协议,域名,资源路径

AJAX-2023.5.2_第6张图片

协议:规定数据格式

http 协议: 超文本传输协议,规定浏览器和服务器之间传输数据的格式
协议范围:http, https,…
AJAX-2023.5.2_第7张图片

域名

域名:标记服务器在互联网中位置
AJAX-2023.5.2_第8张图片

资源路径

资源路径:也就是接口地址,后台人员提供
AJAX-2023.5.2_第9张图片

获取 - 新闻列表

AJAX-2023.5.2_第10张图片

URL 查询参数

AJAX-2023.5.2_第11张图片
在发起ajax请求时如何携带参数?
如果是get请求,可以用?拼接的方式或者是params的方式传参

  • get请求,可以用?拼接的方式传参
<body>
    <p>城市列表</p>
    <!-- 引入ajax -->
    <!-- 第一步:采用CDN在线地址的方式引入axios插件 -->
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
    <script>
        axios({
            // ,默认是get请求
            url: 'http://hmajax.itheima.net/api/city?pname=辽宁省'//pname是后台要求的字段,不能随便切换
        }).then(res => {
            console.log(res)

        })
    </script>

</body>

AJAX-2023.5.2_第12张图片

  • params的方式传参
<body>
    <p>城市列表</p>
    <!-- 引入ajax -->
    <!-- 第一步:采用CDN在线地址的方式引入axios插件 -->
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
    <script>
        axios({
            // 默认是get请求
            // url: 'http://hmajax.itheima.net/api/city?pname=辽宁省'//pname是后台要求的字段,不能随便切换
            url: 'http://hmajax.itheima.net/api/city',
            params: {
                pname: '江苏省'
            }
        }).then(res => {
            console.log(res)

        })

    </script>

AJAX-2023.5.2_第13张图片

常用请求方法和数据提交

常用请求方法: get,post,put,delete

AJAX-2023.5.2_第14张图片
(1) get请求: 作用是用来获取数据
(2) post请求: 常用来提交数据,比如说表单数据的提交
AJAX-2023.5.2_第15张图片
axios错误处理:在then方法的后面,通过点语法调用catch方法,传入回调函数并定义形参
AJAX-2023.5.2_第16张图片
获取错误信息
AJAX-2023.5.2_第17张图片

(3) put请求:用来修改数据

  • List item

(4) delete请求:删除数据

HTTP协议-报文

HTTP 协议一请求报文

AJAX-2023.5.2_第18张图片
请求报文的组成部分有

  1. 请求行:请求方法,URL,协议
  2. 请求头:以键值对的格式携带的附加信息,比如: Content-Type
  3. 空行: 分隔请求头,空行之后的是发送给服务器的资源
  4. 请求体:发送的资源
    AJAX-2023.5.2_第19张图片
    接口调试在network中查看 (主要查看接口地址、请求方式、携带的参数)

AJAX-2023.5.2_第20张图片

HTTP 协议一响应报文

AJAX-2023.5.2_第21张图片

  • 响应状态码
    AJAX-2023.5.2_第22张图片
    响应报文 (重点关注响应状态码和响应回来的数据)
    AJAX-2023.5.2_第23张图片

接口文档

AJAX-2023.5.2_第24张图片
AJAX-2023.5.2_第25张图片

案例 - 用户登录

AJAX-2023.5.2_第26张图片

  1. 给登录按钮添加点击事件
  2. 获取输入框的值
  3. 进行表单校验
  4. 如果表单校验成功,发起接口请求
  5. 封装一个提示信息的方法,如果登陆成功,则是成功的提示
  6. 代码优化,通过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>11.案例_登录</title>
    <!-- 引入bootstrap.css -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/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 " 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:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
        document.querySelector('.btn').addEventListener('click', function () {
            const username = document.querySelector('.username').value
            const password = document.querySelector('.password').value
            // 表单校验
            // username: 'wangadidi',
            // password: '123456',
            if (username.length < 8) {
                alert('用户名不少于8位', false)
                alertFn('用户名不少于8位')
                return
            } else if (password.length < 6) {
                alert('密码不少于6位')
                alertFn('密码不少于6位', false)
                return
            }
            axios({
                url: 'http://hmajax.itheima.net/api/login',
                method: 'post',
                data: {
                    username: username,
                    password: password
                }
            }).then((res) => {
                console.log(res)
                alertFn(res.data.message, true)
            }).catch(err => {
                console.log(err)
                alertFn(err.response.data.message, false)
            })
        })
        // 封装一个登录信息的方法
        function alertFn(msg, flag) {
            //提示信息框的展示和隐藏是通过 show 这个样式控制的
            //提示信息框的背景色是由bootstrap样式库中的class控制的 成功用alert-success  失败用alert-danger
            const alertDom = document.querySelector('.alert')
            alertDom.classList.add('show')//显示信息提示框
            alertDom.innerHTML = msg//动态展示信息提示文本
            //信息提示背景色的控制
            // 如果传递的参数是true,代表校验通过或者登录成功 alert-success
            // 如果传递的参数是false,代表校验失败或者登录失败 alert-danger
            alertDom.classList.add(flag ? 'alert-success' : 'alert-danger')
            //隔一秒之后,提示信息框隐藏
            setTimeout(() => {
                alertDom.classList.remove('show')
                // 将背景色移除
                alertDom.classList.remove(flag ? 'alert-success' : 'alert-danger')
            }, 1000)
        }

    </script>
</body>

</html>
  • alert-danger
    AJAX-2023.5.2_第27张图片
  • alert-success
    AJAX-2023.5.2_第28张图片

form-serialize 插件

作用: 快速收集表单元素的值
代码优化,通过serialize插件快速收集表单中的值
AJAX-2023.5.2_第29张图片

const form=document.querySelector('.example-form')
const data=serialize(form,{hash:true ,empty:true})
//hash是true时,数据会收集到一个对象里面
//hash是false时,表单数据会以字符串拼接的方式收集
//empty是true时,可以收集空数据
//empty是false时,不可以收集空数据

第一步: 给input标签添加name属性,用于收集数据
第二步: 获取表单的DOM

总结

AJAX-2023.5.2_第30张图片

AJAX-2023.5.3

图书管理案例

  1. 图书馆里列表的查询功能
  • 查看接口文档,发起请求(通过axios发起get请求,通过params携带参数)
  • 请求成功,后台返回数据,获取数据,渲染页面
  1. 图书馆里新增功能
  • 给按钮添加点击事件
  • 弹出弹框
  • (录入信息,保存信息 ) 点击保存按钮时收集(通过插件serialize收集表单信息)表单信息,调用接口
  • 重新渲染表格数据,关闭弹框,重置表单
  1. 图书管理的删除功能
  • 给删除按钮绑定点击事件
  • 调用删除接口,携带删除id
  • List item
  • 问题1 事件如何绑定?
  • List item
    问题2 删除的id从哪里来
  1. 图书的编辑功能
  • 点击编辑按钮,打开弹层
  • 调用详情接口,回填数据
  • 点击修改按钮,调用修改接口
  • 接口调用成功后,关闭弹层,更新表格数据
  1. 图片上传
  • 打开文件框,通过type为file的input标签
    打开本地文件
  • 选择图片,点击本地电脑文件筐的打开按钮之后,会触发input标签的change事
  • 在change事件处理函数里面可以获取选择的图片的原始信息
  • 调用上传图片的接口,将获取的图片信息以formData的参数形式传递给后台
  • 接口调用成功后,后台会返回一个图片的url地址
  • 将返回的图片的url地址赋给图片标签的src属性
    AJAX-2023.5.2_第31张图片
  1. 更换背景案例
  • 和上传图片步骤一样,用到了localeStorage本地存储目标
  1. 个人信息设置案例实现
  • 页面的数据回填实现
    ①调用个人消息接口,获取数据
    ②跟据返回的数据分三种情况进行回填
    头像的回填
    表单的回填
    单选框的回填

AJAX-2023.5.4

AJAX原理 - XMLHttpRequest

定义:**XMLHttpRequest (XHR) 对象用于与服务器交互。**通过XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在AJAX 编程中被大量使用。
关系: axios 内部采用 XMLHttpRequest 与服务器交互
AJAX-2023.5.2_第32张图片

使用 XMLHttpRequest

步骤:

  1. 创建 XMLHttpRequest 对象
  2. 配置请求方法和请求 url 地址
  3. 监听 loadend 事件,接收响应结果
  4. 发起请求
    AJAX-2023.5.2_第33张图片
原生ajax实现步骤
   <script>
        // 第一步:创建XMLHttpRequest实例对象
        const xhr = new XMLHttpRequest()
        //第二步: 配置请求方式,以及接口地址
        xhr.open('get', 'http://hmajax.itheima.net/api/province')
        //第三步:监听loadend事件,介绍响应结果
        xhr.addEventListener('loadend', () => {
            // 响应消息通过 xhr.response获取
            //备注:由于原生的请求返回的数据是Json字符串,需要用JSON.parse转换
            console.log(JSON.parse(xhr.response));
        })
        // 第四步: 发起请求
        xhr.send()
    </script>

AJAX-2023.5.2_第34张图片

XMLHttpRequest - 查询参数

定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
AJAX-2023.5.2_第35张图片

案例_地区查询

AJAX-2023.5.2_第36张图片
原生写法:获取城市列表

<script>
        // 练习get请求携带参数
        // 第一步:创建XMLHttpRequest实例对象
        const xhr = new XMLHttpRequest()
        //第二步: 配置请求方式,以及接口地址
        xhr.open('get', 'http://hmajax.itheima.net/api/city?pname=山东省')
        //第三步:监听loadend事件,介绍响应结果
        xhr.addEventListener('loadend', () => {
            // 响应消息通过 xhr.response获取
            //备注:由于原生的请求返回的数据是Json字符串,需要用JSON.parse转换
            console.log(JSON.parse(xhr.response).list)
        })
        // 第四步: 发起请求
        xhr.send()
    </script>

AJAX-2023.5.2_第37张图片

<script>
        //点击查询按钮时,发起原生的ajax请求
        document.querySelector('.btn').addEventListener('click', function () {
            let pname = document.querySelector('.province').value
            let cname = document.querySelector('.city').value
            let obj = new URLSearchParams({
                pname: pname,
                cname: cname
            })
            let queryParams = obj.toString()
            console.log(queryParams)
            // 发起原生的ajax请求
            // 第一步:创建XMLHttpRequest实例对象
            const xhr = new XMLHttpRequest()
            //第二步: 配置请求方式,以及接口地址
            //get请求普通的传参方式
            //通过方法快速生成拼接参数的方式:
            // (1) serialize方法,只需要将serialize(form,{hash:false})
            // (2)
            xhr.open('get', `http://hmajax.itheima.net/api/area?pname=${pname}&cname=${cname}`)
            //第三步:监听loadend事件,介绍响应结果
            xhr.addEventListener('loadend', () => {
                // 响应消息通过 xhr.response获取
                //备注:由于原生的请求返回的数据是Json字符串,需要用JSON.parse转换
                // console.log(JSON.parse(xhr.response).list)
                let list = JSON.parse(xhr.response).list
                const htmlStr = list.map(item => {
                    return `
  • ${item}
  • `
    }).join('') document.querySelector('.list-group').innerHTML = htmlStr }) // 第四步: 发起请求 xhr.send() }) </script>

    AJAX-2023.5.2_第38张图片

    teacher笔记

    目标1:ajax的原理:
    就是浏览器通过XMLHttpRequest对象和服务端进行通信,特点是可以异步的在不刷新页面的情况下局部的修改数据,axios的底层就是通过它实现的,做了封装之后,使用更加方便
    目标2:原生ajax请求的使用步骤
    第一步:创建XMLHttpRequest实例对象
    const xhr = new XMLHttpRequest()
    //第二步:配置请求方式,以及接口地址
    xhr.open(‘get’, ‘http://hmajax.itheima.net/api/province’)
    //第三步:监听loadend事件,介绍响应结果
    xhr.addEventListener(‘loadend’, () => {
    //响应消息通过 xhr.response获取
    //备注:由于原生的请求返回的数据是Json字符串,需要用JSON.parse转换
    console.log(JSON.parse(xhr.response))
    })
    //第四步:发起请求
    xhr.send()
    目标3:原生get请求方式传参
    (1)get请求普通的传参方式,?拼接 http://hmajax.itheima.net/api/city?pname=辽 宁 省
    (2)通过方法快速生成拼接参数的方式:
    serialize方法,只需要将serialize(form,{hash:false})
    通过 URLSearchParams方法构造字符串拼接参数URLSearchParams
    目标4:如何采用原生的ajax发起post请求?
    post请求注意事项:
    (1)post请求需要设置请求头: xhr.setRequestHeader(‘Content-Type’, ‘application/json’)
    (2)post请求在携带参数时需要转换为json字符串携带在请求体中:xhr.send(JSON.stringify())
    问题:get请求和post请求传参的区别?
    get请求的参数是携带在url地址后面的,它是明文的
    post请求的参数是携带在请求体中,没有出现在url地址后面,它是暗文的
    问题1:axios为什么可以发起请求?
    是因为底层是XMLHttpRequest对象和服务端进行交互的
    问题2:aixos发起的请求为什么可以.then(),,为什么可以.catch()
    是因为axios方法在调用完毕之后,返回的是一个Promise对象,对象原型上面有then和catch方法
    目标5:什么是Promise?
    Promise是为解决会解决回调地狱而产生的,可以很好的,清晰的处理异步任务,获取成功的结果或者失败的信息
    问题:什么是回调地狱?
    多层函数的嵌套容易造成回调地狱,回调地狱本身不是错,只是代码比较冗余,结构不够清晰,不好维护,可以通过Promise链式调用的方式解决回调地狱问题
    目标6:如何使用Promise?
    创建了一个Promise实例对象
    const p = new Promise((resolve, reject) => {
    //在这里模拟一个异步任务,看如何获取异步任务执行的结果
    setTimeout(() => {
    // console.log(132456)
    //如果异步任务执行执行成功了,会调用resolve方法,会在then方法里面拿到resolve之后的 结果
    // resolve(‘执行成功了’)
    //如果异步任务执行失败,则会调用reject方法,会在catch中拿到执行失败的信息
    reject(‘执行失败了’)
    }, 2000)
    })
    //通过打印发现,Promise实例对象原型上面有then方法和catch方法
    p.then(result => {
    console.log(result)
    }).catch(err => {
    console.log(err)
    })
    目标7:用Promise封装了一个简单的ajax请求
    目标8:Promise的三种状态:
    (1) pending:正在请求中,不知道是成功还是失败
    (2) fulfilled:执行成功的状态,调用了resolve方法
    (3) rejected:执行失败的状态,调用了reject方法
    目标9:封装一个自己的axios

    自己封装的ajax

    AJAX-2023.5.2_第39张图片

    AJAX-2023.5.6

    输入框的input事件会在输入时频繁触发,如果调用后台接口,对服务器压力比较大如何解决?

    // 通过防抖解决,什么是防抖? (频繁触发的事件只触发最后一次)
    // 用户在输入内容时, 停下来n秒后, 再去调用接口执行任务.还没到n秒, 在输入框中又输入内容了, 这时候会清空定时器, 重新计时.直到停下来n秒后.

    同步代码和异步代码

    同步代码:一行一行的执行,上一行执行完毕才能执行下一行

    我们应该注意的是,实际上浏览器是按照我们书写代码的顺序一行一行地执行程序的。浏览器会等待代码的解析和工作,在上一行完成后才会执行下一行。这样做是很有必要的,因为每一行新的代码都是建立在前面代码的基础之上的。
    这也使得它成为一个同步程序.

    同步代码:逐行执行,需原地等待结果后,才继续向下执行

    异步代码(耗时):异步代码一般是比较耗时的任务,为了不阻塞其他代码的执行,异步代码会被添加到任务队列中,等待同步代码执行完毕才去执行异步代码

    异步编程技术使你的程序可以在执行一个可能长期运行的任务的同时继续对其他事件做出反应而不必等待任务完成。与此同时,你的程序也将在任务完成后显示结果。

    异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数

    例子: 回答打印数字的顺序是什么 ?

    在这里插入图片描述

    JS 中有哪些异步代码?(异步代码一般都带有回调函数)

    setTimeout / setInterval
    事件处理函数
    ajax请求

    异步代码如何接收结果?

    依靠回调函数来接收

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

    回调地狱:多层回调函数的嵌套就会形成回调地狱,代码结构比较乱,不够清晰

    AJAX-2023.5.2_第40张图片
    回调地狱的使用场景 :下一个接口的参数就是依赖于上一个接口的返回结果时
    如何避免回调地狱:Promise链式调用
    通过Promise的链式调用万式链式调用就是在上一个then方法里面继续返回一个新的Promise对象然后继续调用then方法,依次类推
    备注:要学会自己将一个普通的方法变的支持Promise

    AJAX-2023.5.2_第41张图片

    Promise - 链式调用

    概念:依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束
    细节: then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果
    AJAX-2023.5.2_第42张图片

    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
        <script>
            //需求: 查询省市区数据
            // 如果一个方法返回的是一个promise,就可以.then
            // 第一步:发起axios请求,查询省的数据
            let pname = ''
            axios({
                url: 'http://hmajax.itheima.net/api/province',
                method: 'get',
            }).then(res1 => {
                console.log(res1)
                pname = res1.data.list[2]//得到一个省份的名字---河北省
                //第二步: 根据河北省这个参数查询河北省下面的市
                // 备注:axios方法调用完毕之后返回的是一个Promise,底层已经做了封装
                return axios({
                    url: 'http://hmajax.itheima.net/api/city',
                    method: 'get',
                    params: {
                        pname: pname
                    }
                })
            }).then(res2 => {
                // 第三步:在这里获取城市的数据
                console.log(res2)
                let cname = res2.data.list[0]
                // 第四步:根据省市查询市下面的的区的数据
                return axios({
                    url: 'http://hmajax.itheima.net/api/area',
                    method: 'get',
                    params: {
                        pname: pname,
                        cname: cname
                    }
                })
            }).then(res3 => {
                console.log(res3)
                // let cname = res3.data.list[0]
                // 第五步:获取区的数据
            })
        </script>
    
    总结: Promise的使用场景:

    (1)一些封装好的插件,底层返回的是Promise,比如axios,组件库中的一些方法等
    (2)根据需求,如果想把一个普通方法变得支持Promise,那么可以用到
    (3)如果要进行链式调用,使用Promise
    备注: Promise比回调地狱的方式要结构清晰,但还不是最简便的,最简便的写法是async和await

    async 和 await 使用

    async 函数和await

    async 函数是使用 async 关键字声明的函数。async 函数是 AsyncFunction 构造函数的实例,并且其中允许使用 await 关键字。async 和 await 关键字让我们可以用一种更简洁的方式写出基于 Promise 的异步行为,而无需刻意地链式调用 promise。
    概念:在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值
    AJAX-2023.5.2_第43张图片

    什么是async和await?

    AJAX-2023.5.2_第44张图片
    async和await是异步编程的更简洁的方案,是Promise的语法糖,升级方案,代码更加简洁
    特点:
    (1)await 必须搭配async
    (2) await 后面修饰的是一个Promise,会等待拿到Promise执行成功之后的结果
    (3)等待await 修饰的Promise拿到结果之后,才去执行下一行代码
    使用场景: 经常搭配axios接口请求,获取接口请求之后的结果
    总结:只要以后某个方法调用完毕返回的是一个Promise,就可以.then或者用await修饰,拿到结果

     <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
        <script>
            async function getArea() {
                // await修饰的是一个Promise,而axios方法调用返回的就是一个Promise
                // await 必须搭配 async,async需要添加在await所在的父级函数前面
                let proObj = await axios({ url: 'http://hmajax.itheima.net/api/province', method: 'get', })
                console.log(proObj)
                let pname = proObj.data.list[3]
                // 等待拿到省份信息之后,再去调用城市接口
                let cityObj = await axios({ url: 'http://hmajax.itheima.net/api/city', method: 'get', params: { pname: pname } })
                console.log(cityObj)
                //等待拿到城市数据之后,再去调用区的接口
                let cname = cityObj.data.list[0]
                let areaObj = await axios({ url: 'http://hmajax.itheima.net/api/area', method: 'get', params: { pname: pname, cname: cname } })
                console.log(areaObj)
            }
            getArea()
        </script>
    

    AJAX-2023.5.2_第45张图片

    async函数和await 捕获错误

    AJAX-2023.5.2_第46张图片

     <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
        <script>
            async function getArea() {
                try {
                    // await修饰的是一个Promise,而axios方法调用返回的就是一个Promise
                    // await 必须搭配 async,async需要添加在await所在的父级函数前面
                    let proObj = await axios({ url: 'http://hmajax.itheima.net/api/province', method: 'get', })
                    console.log(proObj)
                    let pname = proObj.data.list[3]
                    // 等待拿到省份信息之后,再去调用城市接口
                    let cityObj = await axios({ url: 'http://hmajax.itheima.net/api/city', method: 'get', params: { pname: pname } })
                    console.log(cityObj)
                    //等待拿到城市数据之后,再去调用区的接口
                    let cname = cityObj.data.list[0]
                    let areaObj = await axios({ url: 'http://hmajax.itheima.net/api/area', method: 'get', params: { pname: pname, cname: cname } })
                    console.log(areaObj)
                } catch (err) {
                    // 捕获错误
                    console.log(err)
                }
            }
    
            getArea()
        </script>
    

    事件循环-EventLoop

    js中为什么会有事件循环机制?

    因为is是单线程的,是一行一行执行的,为了让一些耗时的任务不阻塞其他代码的执行,从而设计了事件循环机制

    事件循环

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

    事件循环执行机制的执行流程是什么?

    目标6: 事件循环执行机制的执行流程是什么?
    js在执行代码时,遇到同步代码,会在执行栈中立即执行,遇到异步代码时,异步代码先会被添加到浏览器宿主环境中,浏览器宿主环境会把异步代码的回调函数添加到任务队列中,等同步代码执行完毕执行栈空闲时,反复从任务队列中获取异步代码的回调函数去执行,这就形成了事件循环

    AJAX-2023.5.2_第49张图片
    AJAX-2023.5.2_第50张图片
    AJAX-2023.5.2_第51张图片

    总结

    1.什么是事件循环?
    执行代码和收集异步任务,在调用栈空闲时,反复调用任务队列里回调函数执行机制
    2.为什么有事件循环?
    JavaScript 是单线程的,为了不阻塞 JS 引擎,设计执行代码的模型
    3.JavaScript 内代码如何执行?
    执行同步代码,遇到异步代码交给宿主浏览器环境执行
    异步有了结果后,把回调函数放入任务队列排队
    当调用栈空闲后,反复调用任务队列里的回调函数

    AJAX-2023.5.2_第52张图片

    宏任务与微任务

    ES6 之后引入了 Promise 对象, 让 JS 引警也可以发起异步任务
    异步任务分为:
    宏任务:由浏览器环境执行的异步代码
    微任务:由 JS 引擎环境执行的异步代码
    Promise 本身是同步的,而then和catch回调函数是异步的
    AJAX-2023.5.2_第53张图片
    目标7: 什么是宏任务和微任务?
    异步任务还可以继续分为宏任务和微任务大部分的异步任务都属于宏任务,例如: script标签、定时器/延时器、aax请求、事件交互等微任务: Promise的then方法是个微任务
    备注: Promise本身是个同步任务,它的then方法和catch方法是异步的
    问题:遇到这样的既又宏任务,又有微任务的代码,又是怎么样一个执行流程?
    总结:执行顺序优先级:同步任务>微任务>宏任务

    AJAX-2023.5.2_第54张图片

    Promise.all 静态方法

    AJAX-2023.5.2_第55张图片

    <body>
        <ul>
            <li></li>
        </ul>
        <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
    
        <script>
            const p1 = axios({
                url: 'http://hmajax.itheima.net/api/weather',
                method: 'get',
                params: {
                    city: '310100',
                }
            })
            const p2 = axios({
                url: 'http://hmajax.itheima.net/api/weather',
                method: 'get',
                params: {
                    city: '440100',
                }
            })
            const p3 = axios({
                url: 'http://hmajax.itheima.net/api/weather',
                method: 'get',
                params: {
                    city: '330100',
                }
            })
            const p4 = axios({
                url: 'http://hmajax.itheima.net/api/weather',
                method: 'get',
                params: {
                    city: '610100',
                }
            })
            // all方法里面的参数是一个数组,数组里面的是要执行的多个任务
            const p = Promise.all([p1, p2, p3, p4])
            p.then(res => {
                // res是一个数组,拿到的是所有接口请求,成功之后的结果
                console.log(res)
                let str = res.map(item => {
                    // item是每个接口的返回结果,是一个对象
                    let city = item.data.data.area
                    let weather = item.data.data.weather
                    return `
  • ${city}----${weather}
  • `
    }).join('') document.querySelector('ul').innerHTML = str }) </script> </body>

    AJAX-2023.5.2_第56张图片

    作业
       // 4.用自己的语言描述下下面这段代码的执行机制,以及输出结果
            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)
       		// 1,7,5,6,2,3,4
    
    

    AJAX-2023.5.2_第57张图片

    AJAX-2023.5.2_第58张图片
    AJAX-2023.5.2_第59张图片

    AJAX-2023.5.7

    案例 - 商品分类

    目标1: 商品分类案例实现:
    第一步:调用一级分尖的接口,获取一级分尖的数据,里面包含一级分尖的id
    第二步:拿所有的一级分类的id去请求二级分类的数据,会将所有数据返回到一个数组里面
    第三步:拿到数据之后开始遍历渲染界面

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>案例_分类导航</title>
      <link rel="stylesheet" href="./css/index.css">
    </head>
    
    <body>
      <!-- 大容器 -->
      <div class="container">
        <div class="sub-list">
          <!-- <div class="item">
            <h3>分类名字</h3>
            <ul>
              <li>
                <a href="javascript:;">
                  <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
                  <p>巧克力</p>
                </a>
              </li>
              <li>
                <a href="javascript:;">
                  <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
                  <p>巧克力</p>
                </a>
              </li>
              <li>
                <a href="javascript:;">
                  <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
                  <p>巧克力</p>
                </a>
              </li>
            </ul>
          </div> -->
        </div>
      </div>
      <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
      <script>
        /**
         * 目标:把所有商品分类“同时”渲染到页面上
         *  1. 获取所有一级分类数据
         *  2. 遍历id,创建获取二级分类请求
         *  3. 合并所有二级分类Promise对象
         *  4. 等待同时成功后,渲染页面
        */
        axios({
          url: 'http://hmajax.itheima.net/api/category/top',
          method: 'get',
        }).then(res => {
          console.log(res)
          // 获取一级分类的所有数据
          let firstList = res.data.data
          // 对一级分类数据进行遍历,取出每个一级分类的id,调用二级分类的接口,同时发起多个请求 
          let promiseList = firstList.map(item => {
            // item是每个对象,要用里面的一级分类的id
            return axios({
              url: 'http://hmajax.itheima.net/api/category/sub',
              mathod: 'get',
              params: {
                id: item.id
              }
            })
          })
          console.log(promiseList)
          // 接下来用promise.all一次性发起多个接口请求,获取所有二级分类的数据
          const result = Promise.all(promiseList)
          // 由于Promise.all调用完毕之后返回的是一个Promise
          result.then(res2 => {
            // console.log(res2)
            // res2代表的是获取的所有二级分类的数据,是一个数组
            let str = res2.map(v => {
              // v代表的是每个对象,是每个一级分类所对应的二级分类的数据
              let name = v.data.data.name//取出一级分类的名称
              let childList = v.data.data.children//取出的是二级分类的数据,是一个数组
              // 二级分类的数据是一个数组, 还要进一步的进行遍历
              return ` 

    ${name}

    `
    }).join('') // console.log(str, 'nikesddghkj.') // 渲染到界面 document.querySelector('.sub-list').innerHTML = str }) }) </script> </body> </html>

    AJAX-2023.5.2_第60张图片

    案例 - 学习反馈

    目标2:学习反馈案例实现
    第一步:页面打开调用省份接口展示在下拉框中
    第二步:点击省份下拉框中的数据,会触发下拉框的chang事件,在change事件处理函数中调用城市接
    口,获取所有的城市信息
    第二步:点击城市下拉框中的数据,会触发下拉框的chang事件,在change事件处理函数中调用区数据接口,获取所有的区信息

    async function getProvince() {
        let res = await axios({
            url: 'http://hmajax.itheima.net/api/province',
            method: 'get',
        })
        console.log(res)
        let proList = res.data.list
        let proStr = res.data.list.map(pro => {
            return `   ">${pro}`
        }).join('')
        document.querySelector('.province').innerHTML = `` + proStr
    
    }
    // 调用获取省份数据的接口
    getProvince()
    let pname = ''
    // 选择省份查询市的数据
    document.querySelector('.province').addEventListener('change', async function (e) {
        console.log(e.target.value)
        pname = e.target.value
        let cityObj = await axios({
            url: 'http://hmajax.itheima.net/api/city',
            method: 'get',
            params: {
                pname//选择省份名称
            }
        })
        console.log(cityObj)
        let cityList = cityObj.data.list//获取到的是城市列表的数组
        let cityStr = cityList.map(city => {
            return `">${city}`
        }).join('')
        // 获取城市下拉框的DOM
        document.querySelector('.city').innerHTML = `` + cityStr
        //由于省和区之间没有关联关系,选择完省之后,需要将区的数据重置
        document.querySelector('.area').innerHTML = ``
    })
    // 选择城市查询地区的数据
    document.querySelector('.city').addEventListener('change', async function (e) {
        console.log(e.target.value)
        let areaObj = await axios({
            url: 'http://hmajax.itheima.net/api/area',
            method: 'get',
            params: {
                pname,//选择省份名称
                cname: e.target.value
            }
        })
        console.log(areaObj)
        let cityList = areaObj.data.list//获取到的是城市列表的数组
        let cityStr = cityList.map(area => {
            return `">${area}`
        }).join('')
        document.querySelector('.area').innerHTML = `` + cityStr
    })
    ///点击提交按钮提交表单数据
    document.querySelector('.submit').addEventListener('click', async function () {
        //点击提交数据之后收集表单数据
        //第一步:检查input标签中有没有name//第二步:获取表单的DOM
        const form = document.querySelector('.info-form')
        const data = serialize(form, { hash: true, empty: true })
        console.log(data)
        try {
            // 发起接口请求
            let res = await axios({
                url: 'http://hmajax.itheima.net/api/feedback',
                method: 'post',
                data: data
            })
            console.log(res)
            alert(res.data.message)
        } catch (err) {
            console.log(err)
            alert(err.response.data.message)
        }
    })
    
    

    AJAX-2023.5.2_第61张图片

    Node.js 安装与使用

    AJAX-2023.5.2_第62张图片

    AJAX-2023.5.2_第63张图片
    node环境的安装
    (1)一路next,无脑安装. 默认安装在c盘
    (2)window+R,打开终端(黑窗口),输入cmd,打开电脑终端
    (3)输入node -v查看node是否安装以及node的版本
    AJAX-2023.5.2_第64张图片

    什么是Node.js?

    Node.js 是一个跨平台 JavaScript 运行环境,使开发者可以搭建服务器端的 JavaScript 应用程序
    概念: 使用 Node.js 编写后端程序 / 支持前端工程化
    后端程序:提供接口和数据,网页资源等
    前端工程化:对代码压缩,转译,整合(使用各种工具,提升效率)

    什么是Node.js?

    (1)以前js的运行环境是浏览器,node也是js的运行环境
    (2)node的作用可以搭建服务,开发后台接口,可以实现前端工程化 (代码的压缩、编译等

    Node.js 为何能执行 JS?

    首先:浏览器能执行 JS 代码,依靠的是内核中的 V8 引擎(C++ 程序)
    其次:Node.js 是基于 Chrome V8 引擎进行封装(运行环境)
    区别:都支持 ECMAScript 标准语法,Node.js 有独立的 API
    注意: Node.js 环境没有 DOM 和 BOM 等
    AJAX-2023.5.2_第65张图片

    打开终端的三种方法

    ①方法1打开终端
    直接在vscode中右键文件–>打开集中终端
    AJAX-2023.5.2_第66张图片
    ②方法2打开终端
    在文件所在位置单机文件位置,输入cmd,回车,打开终端
    AJAX-2023.5.2_第67张图片
    ③方法3打开终端
    在文件所在位置shift+右键
    AJAX-2023.5.2_第68张图片

    fs 模块

    fs 模块 - 读写文件
    模块:类似插件,封装了方法/属性
    fs 模块:封装了与本机文件系统进行交互的,方法/属性
    语法:

    1. 加载 fs 模块
    2. 写入文件内容
    3. 读取文件内容

    AJAX-2023.5.2_第69张图片
    AJAX-2023.5.2_第70张图片

    读取的数据是Buffer数据流—>转换

    AJAX-2023.5.2_第71张图片
    ①方法一 :加一个’utf-8’
    AJAX-2023.5.2_第72张图片
    ②方法2:toString转换
    AJAX-2023.5.2_第73张图片

    path 模块

    AJAX-2023.5.2_第74张图片

    目标7: node中的内置path模块
    作用:读写指定路径下的文件
    备注:在读写文件是不建议采用相对路径的写法,是不严格的写法,有可能会出错,因为它会以当前终端所在的目录为参考点去寻找,会出现找不到的情况如何解决?
    采用绝对路径的写法,绝对路径怎么获取的? 通过 dirname可以获取如何用绝对路径拼接文件的路径呢?通过path模块中的join方法

    //需求:在03文件夹下的index.js文件中读取test.js文件中读取test.txt的内容
    const fs = require('fs')
    //下面的这种相对路径的写法,是不严格的写法,有可能会出错,因为它会以当前终端所在的目录为参考点去寻找,会出现找不到的情况,
    //因此不建议采用相对路径的写法,如何解决?
    // 用node中的path模块去解决
    //node中有一个全局变量
    //node中有一个全局变量dirhame.可以获取目前运行文件的绝对路径
    // console.log(__dirname, 'buiuhhhhhhhhh')// (D:\资料U盘\2023.5.7Node.js\2023.5.7_Node.js\03\index.js:8:13)
    //解决方案:就是用绝对路径拼接文件的路径
    //引入path模块
    const path = require('path')
    //底下的代码是在用绝对路径拼接文件的路径
    const filePath = path.join(__dirname, '../', 'test.txt')
    // const filePath = path.join('D:\资料U盘\2023.5.7Node.js\2023.5.7_Node.js\03', '../', 'test.txt')
    fs.readFile('../test.txt', 'utf-8', (err, data) => {
        if (err) {
            console.log(err)
        } else {
            console.log(data)
        }
    })
    
    webpack打包图片资源

    打包图片资源
    从webpack5开始,不再使用loader去打包图片资源,直接在配置文件中配置type:asset,就可以
    注意: 打包图片资源时,有8kb之分,小于8kb的图片会被转成base64
    (1)小于8kb的图片会被转成base64的图片格式,这种图片格式的优势是不用请求资源,直接使用
    (2)大于8kb的图片资源会被单独输出到dist这件夹下面
    有8kb之分的原因: 如果将大于8kb的图片也转成base64,会导致打包之后的文件体积变大

    通过babel对js高级语法在打包时进行降级,以便兼容各种类型的浏览器
    安装axios请求插件,发起接口请求

    npm iaxios
    由于axios插件在开发环境和生产环境中都有用到,因此版本信息会记录在在dependencies核心依赖项里面

    webpack开发服务器的使用

    作用: 每次写完代码执行npm run build打包看效果,很不方便,可以借助于webpack开发服务器它会在边写代码边打包在内存当中,立马能看到写完代码之后的页面效果,同时通过服务的方式访问前端页面

    开发模式和生产模式的区别?

    (1)执行npm run dev命令时,代表的是开发模式,边写代码边调试,可以实现页面热更新效果开发模式的标识是:development
    (2)执行npm run build 命令时,代表的是生产模式,对代码做了打包,压缩,优化,生产模式的标识是: production

    如何快速的去控制台定位错误信息的位置

    在配置文件中添加: devtool: inline-source-map’,//配置这个选项,在打包之后,可以记录源码的位置信息

    案例 - 前端项目压缩

    http 模块 - 创建 Web 服务

    案例 - 浏览时钟

    echarts的使用流程:

    一. 在普通页面中使用echarts
    第一步:得下载echarts包,通过script标签的方式引入本地echarts包
    第二步:用标签创建图表的容器,同时给容器设置宽度和高度
    第三步:初始化echarts实例,需要获取图表容器的DOM
    第四步:调用实例对象的setOption方法,将图标配置项传递进去,绘制图表第五步:查看官方文档修改图标配置项,达到预期的效果
    二. 在框架中使用echarts (在项目阶段学到)

    项目实战任务安排:

    1.各小组选择要开发的大屏项目题材,分配好每个人要开发的图表2.组长任务:
    (1)在本地初始化项目提交到远程仓库,并在远程仓库中添加项目组成员3.组员任务:
    (1)克降项目
    项目克隆下来之后,在本地建立分支进行功能开发2)(3)功能开发完毕之后需要合并代码到主分支,每次开发之前最好先git pul一下,保证是最新的代码(4)所有代码合并完毕之后执行git push命令
    项目答辩 (5月17日下午)4
    (1)协作写一个PPT
    备注:项目实战时间:5月14日至5月17日
    5.代码提交流程:
    1.切换在自己分支上写代码
    2.写完后将自己分支代码提交到本地仓库
    3.将自己本地分支代码推送到远程仓库
    4.切换到master分支后,在合并分支之前git pull拉取最新代码
    5.在master分支拉取最新代码后,再进行分支合并
    6.将合并完的代码推送到远程仓库 git push
    备注:具体命令参考txt文档笔记

    Gitee步骤

    1.在gitee上面创建远程仓库
    2.在本地项目所在的地方执行 git init初始化一个本地仓库
    3.git add.提交到暂存区
    4.git commit -m备注 提交到本地仓库
    5.git remote add origin master 远程仓库地址(如果是第一次提交项目到远程仓库时,需要先建立连接)
    6. git push -u origin masetr
    到此为止,项目就提交到了远程仓库

    其他同学开发时,现在远程仓库克隆项目git clone 远程仓库地址
    开发之前建立自己的本地分支开发代码:
    git checkout-b 分支名称代码开发完毕之后提交代码:
    git add .
    git commit -m完成了tabbar功能
    git push -u origin 分支名称 (将自己本地分支的代码提交到程仓库是为了备份)git checkout master(合并之前先切换到主分支)
    git merge 分支名称(将分支合并到master主分支)
    git push (将合并之后的代码提交到远程仓库)
    git branch -d tabbar(删除本地分支)
    备注:在提交代码之前先拉取最新代码 git pul

    你可能感兴趣的:(ajax,javascript,ecmascript)