ajax工作原理 网页从输入url到呈现过程(TCP ,渲染引擎) 头像上传 下拉加载 节流 防抖 常见状态码

2023-10-29

Ajax工作原理

1.http网络传输协议  :规定 前后端交互的 数据传输格式

           协议 : 规定 前后端交互的数据传输格式

       

      2.http协议组成两个部分

       2.1前端 必须发送 请求报文格式

       2.2后端 必须响应 响应报文格式  

       

      3.请求报文格式组成

       (1) 请求行 : 请求方法和请求地址

       (2)请求头  : 浏览器 告诉 服务器 ,我应该发给你的数据是什么

       (3)请求体  :  请求参数 payload


 

      4 ajax原理 ,设置请求报文

        *发送ajax的过程就是设置请求报文

      (1)响应行 响应状态码 +服务器IP地址     

      (2)响应头  服务器告诉 浏览器 我给你的数据是什么格式

      (3)响应体  服务器响应数据 response

常见的几种状态码

****经典面试题  请求说出你所知道的常见的几种状态码

     2xx (绿色)

        200请求成功

        204:post传输

     3xx(黄色) 重定向(服务器修改浏览器地址)

        302 :重定向,服务器主动修改浏览器地址

        304 :客户端执行了GET,但是文件未变化

     4xx(红色)  前端问题

        400:参数错误

        404:路径错误

        401 :未验证身份

        403 :服务器拒绝访问(没有权限) 会员

        413 : 文件过大

        422:参数错误

     5xx(红色) :服务器问题

        500 :服务器出问题

        503 :服务器维护或者超载

请求报文

响应报文

网页从输入url到呈现过程

网页从输入url到呈现过程

       1.DNS解析 :把域名 解析成 IP地址

       2.TCP三次握手 : 保证http传输的安全可靠

         第一次 浏览器 ->服务器 (你能听到我说话吗,验证浏览器发送)

         第二次 服务器 -> 浏览器 (我听到了,你能听到我说话吗,验证服务器接收,服务器发送)

         第三次 浏览器 -> 服务器(我也听到你说话了,验证浏览器接收)

       3.HTTP连接

          (1) 客户端发送请求

          (2) 服务器处理请求

          (3)服务器响应请求

       4.渲染引擎渲染 :

          (1)解析html :将得到dom树

          (2)解析css :将得到样式树

          (3)将dom树 + 样式树 合并成 渲染树

          (4)绘制渲染树

          (5)呈现页面

TCP三次握手

.TCP三次握手 : 保证http传输的安全可靠

         第一次 浏览器 ->服务器 (你能听到我说话吗,验证浏览器发送)

         第二次 服务器 -> 浏览器 (我听到了,你能听到我说话吗,验证服务器接收,服务器发送)

         第三次 浏览器 -> 服务器(我也听到你说话了,验证浏览器接收)

渲染引擎渲染

        (1)解析html :将得到dom树

          (2)解析css :将得到样式树

          (3)将dom树 + 样式树 合并成 渲染树

          (4)绘制渲染树

          (5)呈现页面

案例 -文件上传

1.1 file表单, 默认自带点击事件,作用是选择文件

1.2 上传文件‘必须’要使用原生内置的FormData对象

(1)文件需要设置单独的请求头 : multipart/form-data

(2)文件以二进制方式传输(文本是utf8编码,但是文件不是)

1.3 file表单有一个特殊的事件onchange事件 : 用户选择了文件就会执行

    /*文件上传思路总结

      1. 给file表单注册onchange事件

        * 当用户选择图片之后执行

      2. 获取用户选择的文件

        *let file= this.files[0]

      3. 使用FormData处理文件

       let浮动=new FormData()

       fd.append('参数名',文件对象)

        * 只有FormData才可以上传文件

      4. 发送ajax请求

        * 文件上传请求方法一定是post, 且请求参数必须为 FormData对象

        (1)formdata会自动帮你的请求头设置成文件请求头 :

        (2)formdata 会自动帮你的文件转成 二进制

      */

<script src="./lib/axios.js"></script>
 <script>
      /*文件上传思路总结 
      1. 给file表单注册onchange事件 
        * 当用户选择图片之后执行
      2. 获取用户选择的文件 
        *let file= this.files[0]
      3. 使用FormData处理文件 
       let浮动=new FormData()
       fd.append('参数名',文件对象)
        * 只有FormData才可以上传文件
      4. 发送ajax请求
        * 文件上传请求方法一定是post, 且请求参数必须为 FormData对象
        (1)formdata会自动帮你的请求头设置成文件请求头 :
        (2)formdata 会自动帮你的文件转成 二进制
      */
      // 给file表单注册onchange事件 
      document.querySelector('#iptFile').addEventListener('change',function(){
        // this :file表单
        // 2.获取用户选择的文件
        console.log(this.files);
        let file=this.files[0]
        //3 文件数据必须要使用内置对象 FormData
    //  (1)文件请求头不一样 :multipart/form-data
    // *formdata会自动帮你设置请求头
    // (2) 文件格式是 二进制传输
    //  *formdata 会自动把你的文件编程二进制传输
    let fd=new FormData()
    // 追加参数 fd.append('参数名',文件数据)
    fd.append('avatar',file)

    // 4.发送ajax设置参数为fd
    axios({
      url:'http://www.liulongbin.top:3009/api/upload/avatar',
      method:'post',
      /* 细节 这里参数直接写浮动,千万不要{fd},因为fd本身就是对象类型 ,不需要单独{}包起来  */
      data: fd,
    
    }).then(res=>{
      //成功回调
      console.log(res)
      // 渲染图片
      document.querySelector('img').src=`http://www.liulongbin.top:3009${res.data.url}`
    })
      })

      
    </script>

自定义头像上传按钮

(1)设置file表单为hidden

(2)给自定义按钮注册点击事件:触发file表单点击

第二种:

(1)label标签的for属性,设置成file表单的id 此时点击label就相当于点击file表单

     label的作用是让某个制定的标签被选中

/*自定义文件上传按钮思路

      第一种 :自定义按钮

      (1)隐藏file表单

      (2)给自定义按钮添加一个点击事件

      (3)点击按钮的时候,触发 file表单的点击

      第二种 :自定义图标

      (1)把你的自定义图标放入label标签中

      (2)label标签for属性,值是表单的id ,只要点击了label就相当于点击了表单

       */

<!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="./lib/bootstrap-v4.6.0.css" />
    <style>
      .thumb-box {
        text-align: center;
        margin-top: 50px;
      }

      .thumb {
        width: 250px;
        height: 250px;
        object-fit: cover;
        border-radius: 50%;
      }
      #btnChoose{
        border-radius: 20px;
        background-image: linear-gradient(45deg,#DC1010, #90ED5A, #2F57E8);
      }
    </style>
  </head>

  <body>
        <a href="http:www.baidu.com">111</a>
    <div class="thumb-box">
      <!-- 头像 -->

      <!-- *** -->
     <label for="iptFile">
      <img src="./images/cover.jpg" class="img-thumbnail thumb" alt="" />
     </label>
      <div class="mt-2">
        <!-- 文件选择框 -->
        <!-- accept 属性表示可选择的文件类型 -->
        <!-- image/* 表示只允许选择图片类型的文件 -->
        <input
          type="file"
          id="iptFile"
          accept="image/*"
          style="display: none"
        />
        <br />
        <!-- 选择头像图片的按钮 -->
        <button class="btn btn-primary" id="btnChoose">
          选择 & 上传图片
        </button>
      </div>
    </div>
    <script src="./lib/axios.js"></script>
    <script>
      /*自定义文件上传按钮思路
      第一种 :自定义按钮
      (1)隐藏file表单
      (2)给自定义按钮添加一个点击事件
      (3)点击按钮的时候,触发 file表单的点击 

      第二种 :自定义图标
      (1)把你的自定义图标放入label标签中
      (2)label标签for属性,值是表单的id ,只要点击了label就相当于点击了表单
       */
document.querySelector('#btnChoose').addEventListener('click',function(){
  // 模拟用户点击表单即可 :相当于点击这个按钮,就是点击表单
  document.querySelector('#iptFile').click()
})
  /*
  
  */
document.querySelector('#iptFile').addEventListener('change',function(){
  console.log(this.files);
        let file=this.files[0]
        //3 文件数据必须要使用内置对象 FormData
    //  (1)文件请求头不一样 :multipart/form-data
    // formdata会自动帮你设置请求头
    // (2)
    let fd=new FormData()
    fd.append('avatar',file)

    // 4.发送ajax设置参数为fd
    axios({
      url:'http://www.liulongbin.top:3009/api/upload/avatar',
      method:'post',
      data: fd,
    
    }).then(res=>{
      //成功回调
      console.log(res)
      document.querySelector('img').src=`http://www.liulongbin.top:3009${res.data.url}`
    })
     
})

    </script>
  </body>
</html>

下拉展示更多案例

下拉加载更多功能

(1)声明全局变量 : index记录当前页数 arr所有的列表

(2)页面注册滚动事件

  计算页面最大滚动距离 = 页面内容高度 -页面可视化高度

 (3)封装 加载列表的ajax,接收一个页码作为参数 const getHeroList=index=>{}

 (4)当滚动到最底部的时候,index++

 (5)加载列表(调用函数)  getHeroList(index)

      *服务器返回数据之后,需要加到arr中再渲染 :arr.push(...res.data.list)

let index=1
let arr=[]
// 节流第一步 :声明开关默认值true
let flag=true
// (2)给页面注册滚动条事件
window.onscroll=function(){
  /*节流第二步:判断开头 ,如果开关是true,则触发事件 + 开关改为false */
  if(flag){
    // 判断是否滚动到最底部
    /* 页面最大滚动距离 scrollTop = 页面内容高度 scrollHight - 页面可视区域高度clientHeight*/
    let maxTop = document.documentElement.scrollHeight - document.documentElement.clientHeight
    let scrollTop = document.documentElement.scrollTop
    /* 如果做了节流处理,这里最好不要完全碰到底部才请求下一页
         因为有可能你碰到底部的时候,刚好flag是false,不会执行的
           像京东 : 如果有节流的话, 一般离底部大概100px的位置就会请求下一页 */
    if(scrollTop>= maxTop -100){
      index++
      console.log(index);
      getHeroList(index)
    }
    // console.log(index);
  }
}
// 节流 只要触发事件事件 .开关改为false
flag =false
/* 节流 开启定时器.节流时间后,把开关改为true*/
setTimeout(function(){
  flag=true
},200)
// 页面一加载,渲染第一页数据
getHeroList(1)

详细参考 

<!-- 导入axios -->
    <script src="./lib/axios.js"></script>
    <script>
      // 页面一开始加载,ajax请求英雄列表

      const getHeroList=index=>{
        axios({
        url: 'https://autumnfish.cn/api/cq/page',
        method: 'get',
        params: { pageNum: index, pageSize: 20 }
      }).then(res => {
        //成功回调
        console.log(res)
        // 先追加到全局数组
        arr.push(...res.data.list)
        // 渲染数组
        renderData(arr)
      })
      }
      /* 封装渲染函数 */
      const renderData = arr => {
        document.querySelector('tbody').innerHTML = arr.map(item => `
    <tr>
                      <td><img src="${item.icon}" alt="" /></td>
                      <td>${item.name}</td>
                      <td>${item.skill}</td>
                    </tr>`).join('')
      }

      /*
      2.输入框keydown
       2.1判断enter键
       2.2获取输入框内容
       2.3发送ajax
       2.4服务器响应渲染数据
      
      */
      document.querySelector('.search').addEventListener('keydown', function (e) {
        if (e.key == 'Enter') {
          // 获取输入框内容
          // let query=document.querySelector('.search').value
          let query = this.value
          axios({
            url: 'https://autumnfish.cn/api/cq',
            method: 'get',
            params: { query }
          }).then(res => {
            if(!res.data.list){
              return alert('已经到最低了')
            }
            //成功回调
            console.log(res)
            renderData(res.data.list)
          })
        }
      })
/*
下拉加载更多功能
(1)声明全局变量 : index记录当前页数 arr所有的列表
(2)页面注册滚动事件(***记得把wrap的那个fixed定位注释掉)
  计算页面最大滚动距离 = 页面内容高度 -页面可视化高度
 (3)封装 加载列表的ajax,接收一个页码作为参数 const getHeroList=index=>{}
 (4)当滚动到最底部的时候,index++
 (5)加载列表(调用函数)  getHeroList(index)
      *服务器返回数据之后,需要加到arr中再渲染 :arr.push(...res.data.list)
*/
let index=1
let arr=[]
// 节流第一步 :声明开关默认值true
let flag=true
// (2)给页面注册滚动条事件
window.onscroll=function(){
  /*节流第二步:判断开头 ,如果开关是true,则触发事件 + 开关改为false */
  if(flag){
    // 判断是否滚动到最底部
    /* 页面最大滚动距离 scrollTop = 页面内容高度 scrollHight - 页面可视区域高度clientHeight*/
    let maxTop = document.documentElement.scrollHeight - document.documentElement.clientHeight
    let scrollTop = document.documentElement.scrollTop
    /* 如果做了节流处理,这里最好不要完全碰到底部才请求下一页
         因为有可能你碰到底部的时候,刚好flag是false,不会执行的
           像京东 : 如果有节流的话, 一般离底部大概100px的位置就会请求下一页 */
    if(scrollTop>= maxTop -100){
      index++
      console.log(index);
      getHeroList(index)
    }
    // console.log(index);
  }
}
// 节流 只要触发事件事件 .开关改为false
flag =false
/* 节流 开启定时器.节流时间后,把开关改为true*/
setTimeout(function(){
  flag=true
},200)
// 页面一加载,渲染第一页数据
getHeroList(1)


   </script>

函数防抖与节流

函数防抖

1.函数防抖 :  单位时间内,频繁触发事件,只会触发最后一次

        2.经典应用场景 : 输入框输入事件  oninput

        3.防抖流程 :

            (1)声明全局变量存储定时器ID

            (2)每一次触发事件的时候,先清除上一次定时器

            (3)开启本次 防抖定时器

 <script>
        /* 
        1.函数防抖 :  单位时间内,频繁触发事件,只会触发最后一次
        2.经典应用场景 : 输入框输入事件  oninput
        3.防抖流程 :
            (1)声明全局变量存储定时器ID
            (2)每一次触发事件的时候,先清除上一次定时器
            (3)开启本次 防抖定时器
        */
    //(1)声明全局变量存储定时器ID
    let timeID =null
    document.querySelector('input').addEventListener('input',function(){
        // 没触发一次事件的时候,先清除上一次定时器

        clearTimeout(timeID)
        // (3)开启本次 防抖定时器
        /*
        定时器中function :指向 window
        箭头函数 :没有this,访问上级this,指向事件源
        */
       timeID=setTimeout(()=>{
           console.log(`发送ajax请求:${this.value}`);
       },300)
    }) 
    
    </script>

 函数节流

1.函数防抖 :  单位时间内,频繁触发事件,只会触发一次

        2.经典应用场景 :解决事件高频触发  滚动条事件,鼠标移动

        3.节流思路 :

            (1) 恒明一个全局开关 let flag=true

            (2) 触发事件的时候,判断开关

               如果是true :触发事件,吧开关改为false

               如果是false :不触发事件

             (3)开启节流定时器,在节流事件之后把开关改为true

 <script>
        /* 
        1.函数防抖 :  单位时间内,频繁触发事件,只会触发一次
        2.经典应用场景 :解决事件高频触发  滚动条事件,鼠标移动
        3.节流思路 :
            (1) 恒明一个全局开关 let flag=true
            (2) 触发事件的时候,判断开关
               如果是true :触发事件,吧开关改为false
               如果是false :不触发事件
             (3)开启节流定时器,在节流事件之后把开关改为true  
        */
    let flag=true
    let i=1
   window.onscroll=function(){
    //    (2) 触发事件的时候,判断开关
    if(flag){
        flag=false
        console.log(`滚动事件触发次数${i++}`);
        // (3)开启节流定时器,在节流事件之后把开关改为true  
        setTimeout(function(){
            flag=true
        },300)
    }
   }
        // 鼠标移动
        // let j=1
        // window.onmousemove=function(){
        //     console.log(`鼠标滚动触发次数${j++}`);
        // }
    </script>

 三种高度  offsetHeight scrollHeight clientHeight

offsetHight   盒子自身的高度

scrollHight   盒子内容的高度

clientHight   盒子视口的高度

scrollTop      页面卷出去的距离

   <style>
        div{
            width: 80px;
            height: 200px;
            border: 10px solid red;
            padding: 20px;
            overflow: auto;
        }
    </style>
</head>
<body>
    <div class="box">
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
        程序员大前端
    </div>
    <script>
        let box = document.querySelector('.box')
        console.log( box.offsetHeight )//盒子自身高度 + 位置
        console.log( box.scrollHeight )//盒子内容高度 + 位置
        console.log( box.clientHeight )//盒子可视区域高度
        
    </script>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ajax工作原理 网页从输入url到呈现过程(TCP ,渲染引擎) 头像上传 下拉加载 节流 防抖 常见状态码 的相关文章