• Ajax同源和跨域和节流防抖


    一、同源策略和跨域请求

    1.同源

    • 同源:说的是两个url之间的对比。
      如果两个url以下三个方面都相同,则这两个url同源,否则非同源。
    • 协议(http、https、file、…)
    • 主机地址(www.itcbc.com)
    • 端口号(:3000)
    http协议默认的端口是 80;  https协议默认的端口是 443
    
    • 1

    img

    2.同源策略

    同源策略(同源政策)是浏览器的一种保护机制。

    如果发送了一个请求,服务器返回结果后,浏览器会判断(检查)打开页面的url 和 **请求的接口地址**是否同源。

    • 如果同源则接收响应结果
    • 如果不同源,则拒绝接收结果(请求失败)

    二、跨域

    凡是违反了同源策略的请求,都是跨域请求

    1.突破跨域的限制

    突破跨域的限制,可以使用JSONP方案 或CORS方案。

    2.CORS方案

    1. 是标准的解决跨域的方案
    2. 兼容性不好(IE10+)
    3. 支持所有的请求方式
    4. 用起来特别方便

    2.1使用CORS方案解决跨域

    后端在做出响应的时候,加一个响应头(Access-Control-Allow-Origin: *)即可。
    前端不需要做任何处理,正常发送Ajax请求即可。

    3.JSONP方案

    1. 不是标准的解决跨域的方案
    2. 是一个古老的方案
    3. JSONP请求和AJAX无关,只支持GET请求

    3.1实现原理:

    • 准备好一个函数,名字随意,用于接收响应结果
    • 使用script标签的src属性请求接口地址,并通过callback把函数名传给服务器即可
    <script>
      // 提前准备好 abc 函数
      function abcd(res) {
        console.log(res)
      }
      
      // abcd({ "id": 100, "name": "hahaha", "age": 20 });
      // 你的函数名是abcd,参数是响应给你的数据
    </script>
    <script src="http://www.xxx/jsonp?callback=abcd"></script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.封装一个发送JSONP请求的函数

    function jsonp({ url, params, success }) {
      // 处理params
      let arr = []
      for (let key in params) {
        arr.push(`${key}=${params[key]}`)
      }
      // console.log(success)
      // 准备好的函数是 success
      // 服务器返回 success(.....) ,调用的是全局中的 success
      // 所以需要把我们的success升级为全局函数
      window.success = success
      let s = document.createElement('script')
      s.src = url + '?callback=success&' + arr.join('&')
      document.body.appendChild(s)
      // script标签什么时候加载完毕。当服务器返回结果后,表示script标签加载的内容加载完毕了
      // 加载完服务器返回的结果,就会触发 load 事件
      s.addEventListener('load', function () {
        document.body.removeChild(s)
      })
    }
    // 点击按钮,调用函数,进行测试
    document.querySelector('button').addEventListener('click', function () {
      jsonp({
        url: 'http://xxx/jsonp',
        params: {
          id: 1,
          appkey: 'huanghun'
        },
        success: function (res) {
          console.log(res)
        }
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    三、淘宝搜索建议案例

    let timer = null
    // 1. 找到输入框,注册input事件(当我们在输入框输入内容的时候就会触发事件)
    document.querySelector('.ipt').addEventListener('input', function () {
      // 马上清除定时器
      clearTimeout(timer)
      // 获取搜索关键字
      let keyword = this.value
      if (keyword === '') return // 关键字为空,不发送请求
      timer = setTimeout(() => {
        // 2. 事件触发后,发送JSONP请求,获取搜索建议
        jsonp({
          url: 'https://suggest.taobao.com/sug',
          params: {
            q: keyword,
            code: 'utf-8'
          },
          success: (res) => {
            // 3. 得到搜索建议之后,把数据渲染到 div#suggest-list 中
            // console.log(res)
            let arr = res.result.map(item => `
    ${item[0]}
    `
    ) // console.log(arr.join('')) document.querySelector('#suggest-list').innerHTML = arr.join('') } }) }, 1000) })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    四、节流案例

    let box = document.querySelector('.box')
    let btn = document.querySelector('.btn-fire')
    btn.addEventListener('click', function () {
      console.log(1)
      // 判断 box 盒子里面有几个图片
      if (box.children.length === 2) return
      // 创建一个热狗
      let newBall = document.createElement('img')
      newBall.src = './img/bullet.png'
      newBall.classList.add('ball')
      // 将热狗加入到盒子中
      box.appendChild(newBall)
    
      // 给热狗加一个动画
      for (let i = 1; i <= 95; i++) {
        setTimeout(() => {
          newBall.style.left = i + '%'
          if (i === 95) {
            // 当热狗跑到头,移除它
            box.removeChild(newBall)
          }
        }, i * 10)
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    五、图片跟随鼠标移动案例

    1.通过定时器实现节流

    <body>
      <img src="./images/tianshi.gif" alt="" style="position: absolute;">
      
      <script>
        let img = document.querySelector('img')
        
        let timer = null
        // 给 document 注册 mousemove 事件,当鼠标移动的时候触发
        document.addEventListener('mousemove', function (e) {
          console.log(123)
          if (timer) { // timer是数字,则不要往下进行
            return
          }
          timer = setTimeout(() => { // 将定时器赋值给 timer,timer就是数字
            console.log('代码执行了一次')
            // 获取鼠标的位置
            let x = e.clientX
            let y = e.clientY
            // console.log(x, y)
            // 设置图片的 left 样式和 top 样式
            img.style.left = (x - 30) + 'px'
            img.style.top = (y - 30) + 'px'
            // 当前定时器执行完毕,重置 timer
            timer = null
          }, 30)
        })
      </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.通过时间差实现节流

    // 节流:单位时间(30ms)内,事件中的计算,最多执行一次
    let img = document.querySelector('img')
    let prev = Date.now() // 1000130
    // 给 document 注册 mousemove 事件,当鼠标移动的时候触发
    document.addEventListener('mousemove', function (e) {
      console.log(111)
      let curr = Date.now() // 1000130
      if (curr - prev >= 30) {
        console.log(222)
        // 获取鼠标的位置
        let x = e.clientX
        let y = e.clientY
        // console.log(x, y)
        // 设置图片的 left 样式和 top 样式
        img.style.left = (x - 30) + 'px'
        img.style.top = (y - 30) + 'px'
        // 重置上一次执行时间
        prev = Date.now()
      }
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    spring整合的redis分布式锁
    ARM-Linux内核基础知识
    CSRF+XSS组合
    哪个版本的JVM最快?
    Prometheus+Grafana监控系统
    C++【STL】【string类的模拟实现】【string类的深浅拷贝】
    07Linux--环境安装
    aspnet zero core 11.3.0 Crack
    蓝桥杯:跑步锻炼
    戳进来,带你走近飞凌嵌入式旗舰级AIoT芯RK3588开发板
  • 原文地址:https://blog.csdn.net/m0_62181310/article/details/126755262