Ajax同源和跨域和节流防抖

一、同源策略和跨域请求

1.同源

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

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>

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)
    }
  })
})

三、淘宝搜索建议案例

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 => `<div class="suggest-item">${item[0]}</div>`)
        // console.log(arr.join(''))
        document.querySelector('#suggest-list').innerHTML = arr.join('')
      }
    })
  }, 1000)
})

四、节流案例

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.通过定时器实现节流

<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>

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()
  }

})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄昏终结者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值