【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】

初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域

  • 1 初识前后端交互
  • 2 原生Ajax
    • 2.1 Ajax基础
    • 2.2 Ajax案例
    • 2.3 ajax请求方式
  • 3 Fetch
    • 3.1 fetch基础
    • 3.2 fetch案例
  • 4 axios
    • 4.1 axios基础
    • 4.2 axios使用
      • 4.2.1 axios拦截器
      • 4.2.2 axios中断器
  • 5 同源策略
  • 6 解决跨域
    • 6.1 jsonp
    • 6.2 其他技术手段

1 初识前后端交互

  • 传统网站的问题:
    1> 为了获取数据,需要重新加载,浪费资源,增加等待时间,性能不好。
    2> 验证表单过程中,一项内容不合格,页面需要重新加载,体验不好。
  • 解决问题:
    1> ajax 全名 async javascript and XML
    2> 是前后台交互的能力
    3> 也就是我们客户端给服务端发送消息的工具,以及接受响应的工具
    4> 是一个默认异步执行机制的功能
  • AJAX的优势:
    1> 不需要插件的支持,原生 js 就可以使用
    2> 用户体验好(不需要刷新页面就可以更新数据)
    3> 减轻服务端和带宽的负担
    4> 缺点: 搜索引擎的支持度不够,因为数据都不在页面上,搜索引擎搜索不到

2 原生Ajax

2.1 Ajax基础

  • 在 js 中有内置的构造函数来创建 ajax 对象;
const xhr = new XMLHttpRequest()
// 上面就是有了一个 ajax 对象
// 我们就可以使用这个 `xhr` 对象来发送 ajax 请求了
  • 配置链接信息;
xhr.open("get","1.json ",true)
// xhr.open('请求方式', '请求地址', 是否异步)
// xhr 对象中的 open 方法是来配置请求信息的
// 第一个参数是本次请求的请求方式 get / post / put / ...
// 第二个参数是本次请求的 url
// 第三个参数是本次请求是否异步,默认 true 表示异步,false 表示同步
  • 创建 ajax 对象以后,我们就使用 ajax 对象的方法去发送请求和接受响应。
xhr.send()
// 使用 xhr 对象中的 send 方法来发送请求
// 上面代码是把配置好信息的 ajax 对象发送到服务端
一、一个基本的ajax请求:
	一个最基本的 ajax 请求就是上面三步
	但是光有上面的三个步骤,我们确实能把请求发送的到服务端
	如果服务端正常的话,响应也能回到客户端,但是我们拿不到响应
	如果想拿到响应,我们有两个前提条件:
		1. 本次 HTTP 请求是成功的,也就是我们之前说的 http 状态码为 200 ~ 299
		2. ajax 对象也有自己的状态码,用来表示本次 ajax 请求中各个阶段
二、ajax 状态码:
	ajax 状态码 —— xhr.readyState
	是用来表示一个 ajax 请求的全部过程中的某一个状态
	readyState === 0: 表示未初始化完成,也就是 `open` 方法还没有执行
	readyState === 1:  表示配置信息已经完成,也就是执行完 `open` 之后
	readyState === 2:  表示 `send` 方法已经执行完成
	readyState === 3:  表示正在解析响应内容
	readyState === 4:  表示响应内容已经解析完毕,可以在客户端使用了
	这个时候我们就会发现,当一个 ajax 请求的全部过程中,只有当 `readyState === 4` 的时候,我们才可以正常使用服务端给我们的数据
	所以,配合 http 状态码为 200 ~ 299
		一个 ajax 对象中有一个成员叫做 `xhr.status` 
 		这个成员就是记录本次请求的 http 状态码的
 	两个条件都满足的时候,才是本次请求正常完成
三、readyStateChange
	在 ajax 对象中有一个事件,叫做 `readyStateChange` 事件
	这个事件是专门用来监听 ajax 对象的 `readyState` 值改变的的行为
	也就是说只要 `readyState` 的值发生变化了,那么就会触发该事件
	所以我们就在这个事件中来监听 ajax 的 `readyState` 是不是到 4 了
四、responseText
	ajax 对象中的 `responseText` 成员
	就是用来记录服务端给我们的响应体内容的
	所以我们就用这个成员来获取响应体内容就可以
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>Documenttitle>
head>
<body>
    <button>aaabutton>
    <script>
        var xhr = new XMLHttpRequest()

        xhr.open("get","1.json ",true)
        // 第一个参数 get post 请求方式
        // 第二个参数 请求地址
        // 第三个参数 是否异步

        xhr.send()

        // 监听
        // 方法一
        /* xhr.onreadystatechange = function() {
            console.log("电话接通");
            console.log(xhr.readyState); // 准备状态
            if(xhr.readyState === 4) {
                // if(xhr.status === 200) {
                if(/^2\d{2}$/.test(xhr.status)) {
                    console.log(JSON.parse(xhr.responseText))
                } else {
                    console.log("error",xhr.responseText);
                }
            }
        } */

        // 方法二
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
                console.log(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
        }
    script>
body>
html>
{
    "name":"xiaowang"
}

【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第1张图片

2.2 Ajax案例

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>Documenttitle>
head>
<body>
    <button id="btn">clickbutton>
    <ul id="list">
        
    ul>
    <script>
        var obtn = document.querySelector('#btn')
        var olist = document.querySelector('#list')
        obtn.onclick = function() {
            var xhr = new XMLHttpRequest()

            xhr.open("get","http://www.xiongmaoyouxuan.com/api/tabs", true) // 后端接口地址

            xhr.send()

            xhr.onload = function() {
                if(/^2\d{2}$/.test(xhr.status)) {
                    // console.log(JSON.parse(xhr.responseText))
                    render(JSON.parse(xhr.responseText))
                } else {
                    console.log("error",xhr.responseText);
                }
            }
        }
        // 渲染页面
        function render(res) {
            console.log(res.data.list);

            var newlist = res.data.list.map(function(item){
                return `
  • ${item.imageUrl}"/>
    ${item.name}
  • `
    }) console.log(newlist); olist.innerHTML = newlist.JSON.join("") }
    script> body> html>
    {
        "data": {
            "list": [
                {
                    "name": "假数据111",
                    "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
                },
                {
                    "name": "假数据222",
                    "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
                },
                {
                    "name": "假数据111",
                    "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
                },
                {
                    "name": "假数据111",
                    "imageUrl": "http://img1.lukou.com/static/p/fb/tab/1/20181211-151644.jpeg"
                }
    
            ]
        }
    }
    

    2.3 ajax请求方式

    • 不同的请求方式:
      1> get 偏向获取
      2> post 偏向提交
      3> put 偏向更新
      4> patch 偏向修改部分
      5> delete 偏向删除信息
      6> head 偏向获取服务器头的信息
      7> option 偏向获取服务器设备信息
      8> connect 保留请求方式

    • 使用get请求方式(不传参数):

    oget.onclick = function() {
    	var xhr = new XMLHttpRequest()
        xhr.open("GET","http://localhost:3000/list", true) // 后端接口地址
        xhr.send()
        xhr.onload = function() {
        	if(/^2\d{2}$/.test(xhr.status)) {
            	console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
    		} else {
            	console.log("error",xhr.responseText);
            }
    	}
    }
    
    • 使用get请求方式(传参数):
    oget.onclick = function() {
    	var xhr = new XMLHttpRequest()
        xhr.open("GET","http://localhost:3000/users?id=1", true)
        xhr.send()
        xhr.onload = function() {
        	if(/^2\d{2}$/.test(xhr.status)) {
            	console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
    		} else {
            	console.log("error",xhr.responseText);
            }
    	}
    }
    
    • 使用post请求方式(传参数):
    opost.onclick = function() {
    	var xhr = new XMLHttpRequest()
        xhr.open("POST","http://localhost:3000/users", true) // 后端接口地址
        // 两种提交方式:
        // form编码 name=kerwin&age=100
        // json {name:"kerwin",age:100}
        // 方式一
        /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
        xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
        // 方式二
        xhr.setRequestHeader("content-type","application/json")
        xhr.send(JSON.stringify({
        	name:"guludunzi",
            age:90
        })) // 数据放在这里
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
            	console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
    	}
    }
    
    • 使用put请求方式(传参数):
    oput.onclick = function() {
        var xhr = new XMLHttpRequest()
        xhr.open("PUT","http://localhost:3000/users/4", true) // 后端接口地址
        // 两种提交方式:
        // form编码 name=kerwin&age=100
        // json {name:"kerwin",age:100}
        // 方式一
        /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
        xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
        // 方式二
        xhr.setRequestHeader("content-type","application/json")
        xhr.send(JSON.stringify({
            username:"guludunzi",
            age:70
        })) // 数据放在这里
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
                console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
        }
    }
    
    • 使用patch请求方式(传参数):
    opatch.onclick = function() {
        var xhr = new XMLHttpRequest()
        xhr.open("PATCH","http://localhost:3000/users/4", true) // 后端接口地址
        // 两种提交方式:
        // form编码 name=kerwin&age=100
        // json {name:"kerwin",age:100}
        // 方式一
        /* xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
        xhr.send(`name=tiechui&age=18`) */ // 数据放在这里
        // 方式二
        xhr.setRequestHeader("content-type","application/json")
        xhr.send(JSON.stringify({
            // username:"guludunzi",
            age:180
        })) // 数据放在这里
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
                console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
        }
    }
    
    • 使用delete请求方式(无参数):
    odelete.onclick = function() {
        var xhr = new XMLHttpRequest()
        xhr.open("DELETE","http://localhost:3000/users/4", true) // 后端接口地址
        xhr.send()
        xhr.onload = function() {
            if(/^2\d{2}$/.test(xhr.status)) {
                console.log(JSON.parse(xhr.responseText))
                // render(JSON.parse(xhr.responseText))
            } else {
                console.log("error",xhr.responseText);
            }
        }
    }
    

    3 Fetch

    • XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱, 而且基于事件的异步模型写起来不友好。
    • 先在集成终端中打开json-server监视:
      【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第2张图片

    3.1 fetch基础

    • 使用get请求方式(不传参数):
    oget.onclick = function() {
        fetch("http://localhost:3000/users")
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 使用get请求方式(传参数):
    oget.onclick = function() {
        fetch("http://localhost:3000/users?id=1")
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 使用post请求方式(传参数):
    opost.onclick = function() {
        fetch("http://localhost:3000/users",{
            method:"post",
            headers:{
                // 两种提交方式:
                // form编码 name=kerwin&age=100
                // json {name:"kerwin",age:100}
                // 方式一
                // "content-type":"application/x-www-form-urlencoded"
                // 方式二
                "content-type":"application/json"
            },
            // body:"name=dazhuang&age=100" // 方式一body
            body:JSON.stringify({
                name:"xiaoli",
                age: 20
            })
        })
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 使用put请求方式(传参数):
    oput.onclick = function() {
        fetch("http://localhost:3000/users/2",{
            method:"put",
            headers:{
                // 两种提交方式:
                // form编码 name=kerwin&age=100
                // json {name:"kerwin",age:100}
                // 方式一
                // "content-type":"application/x-www-form-urlencoded"
                // 方式二
                "content-type":"application/json"
            },
            // body:"name=dazhuang&age=100" // 方式一body
            body:JSON.stringify({
                name:"xiaowang",
                age: 76
            })
        })
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 使用patch请求方式(传参数):
    opatch.onclick = function() {
        fetch("http://localhost:3000/users/2",{
            method:"PATCH",
            headers:{
                // 两种提交方式:
                // form编码 name=kerwin&age=100
                // json {name:"kerwin",age:100}
                // 方式一
                // "content-type":"application/x-www-form-urlencoded"
                // 方式二
                "content-type":"application/json"
            },
            // body:"name=dazhuang&age=100" // 方式一body
            body:JSON.stringify({
                age: 33
            })
        })
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 使用delete请求方式(无参数):
    odelete.onclick = function() {
        fetch("http://localhost:3000/users/2",{
            method:"delete",
        })
        .then(res =>res.json())
        .then(res => {
            console.log(res);
        })
    }
    
    • 以使用get请求方式为例失败处理:
    oget.onclick = function() {
        fetch("http://localhost:3000/users?id=1")
        .then(res =>{
    		if(res.ok){
    			return res.json()
    		}else{
    			return Promise.reject({
    				// 展示出错码和出错原因
    				status:res.status,
    				statusText:res.statusText
    			})
    		}
    	})
        .then(res => {
            console.log(res);
        }).catch(err => {
    		console.log("err", err)
    	})
    }
    

    【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第3张图片

    3.2 fetch案例

    • 通过输入作者姓名找到新闻标题,再根据新闻标题对应的新闻id找到所对应的评论内容。
    • db.json代码:
    {
        "news": [
            { "id" : 1, "title" : "男人看了沉默,女人看了流泪", "author" : "kerwin"},
            { "id" : 2, "title" : "震惊!他年薪仅1元", "author" : "tiechui"},
            { "id" : 3, "title" : "速看!万分危急!", "author" : "gangdan"}
        ],
        "comments": [
            { "id" : 1, "body" : "我是男人", "newsId" : 1 },
            { "id" : 2, "body" : "我是女人", "newsId" : 1 },
            { "id" : 3, "body" : "我年薪2元", "newsId" : 2 },
            { "id" : 4, "body" : "我年薪3元", "newsId" : 2 },
            { "id" : 5, "body" : "1块钱就能买1块钱的东西", "newsId" : 3 },
            { "id" : 6, "body" : "2块钱就能买2块钱的东西", "newsId" : 3 }
        ]
    }
    
    • 基于fetch的01.html代码:
    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>Documenttitle>
    head>
    <body>
        <input type="text" id="search">
        <h1 id="title">h1>
        <ul id="list">ul>
        <script>
            var osearch = document.querySelector('#search')
            var otitle = document.querySelector('#title')
            var olist = document.querySelector('#list')
    
            osearch.oninput = function() {
                fetch(`http://localhost:3000/news?author=${osearch.value}`)
                .then( res => res.json())
                .then( res => {
                    if(res.length > 0) {
                        otitle.innerHTML = res[0].title
                        return fetch(`http://localhost:3000/comments?newsId=${res[0].id}`)
                        .then(res=>res.json())
                    }else {
                        otitle.innerHTML = ""
                        return res
                    }
                }).then(res=>{
                    console.log(res)
                    olist.innerHTML = res.map( item => `
                        
  • ${item.body}
  • `
    ).join("") // join是为了避免中间有逗号 }) }
    script> body> html>
    • fetch结合async await下的01.html代码:
    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>Documenttitle>
    head>
    <body>
        <input type="text" id="search">
        <h1 id="title">h1>
        <ul id="list">ul>
        <script>
            var osearch = document.querySelector('#search')
            var otitle = document.querySelector('#title')
            var olist = document.querySelector('#list')
    
            osearch.oninput = async function() {
                var res = await fetch(`http://localhost:3000/news?author=${osearch.value}`)
                .then( res => res.json())
                var result
                if(res.length > 0) {
                    otitle.innerHTML = res[0].title
                    result = await fetch(`http://localhost:3000/comments?newsId=${res[0].id}`)
                    .then(res=>res.json())
                }else {
                    otitle.innerHTML = ""
                    result = res
                }
                // console.log("111",result)
                olist.innerHTML = result.map( item => `
                    
  • ${item.body}
  • `
    ).join("") // join是为了避免中间有逗号 }
    script> body> html>

    【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第4张图片

    4 axios

    • Axios是一个基于promise 的 HTTP 库,可以用在浏览器和 node.js中。
    • https://www.npmjs.com/package/axios

    4.1 axios基础

    • 使用get请求方式(不传参数):
    oget.onclick = function() {
    	axios.get("http://localhost:3000/users")
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
         })
         // 若失败走.catch
         .catch(err => {
            console.log("err",err)
         })
    }
    
    • 使用get请求方式(传参数):
    oget.onclick = function() {
    	axios.get("http://localhost:3000/users?name=kerwin")
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
         })
         // 若失败走.catch
         .catch(err => {
            console.log("err",err)
         })
    }
    
    • 使用get请求方式(传参数且为对象结构):
    oget.onclick = function() {
    	axios.get("http://localhost:3000/users",{
    		params:{
    			name:"kerwin"
    		}
    	})
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
         })
         // 若失败走.catch
         .catch(err => {
            console.log("err",err)
         })
    }
    
    • 使用post请求方式(传参数):
     opost.onclick = function() {
    	// 以json方式传参数
    	/* axios.post("http://localhost:3000/users",{
        	name:"xiaoming",
            age:18
        }) */
        
        // 以form方式传参数方法一
        // axios.post("http://localhost:3000/users","name=tiechui&age=77")
    
    	// 以form方式传参数方法二
    	const params = new URLSearchParams({name:"dazhuang",age:13});
        axios.post("http://localhost:3000/users",params)
    
    	// 若成功走.then
        .then(res => {
        	console.log(res.data)
        })
        // 若失败走.catch
        .catch(err => {
        	console.log("err",err)
        })
    }
    
    • 使用put请求方式(传参数):
    oput.onclick = function() {
    	axios.put("http://localhost:3000/users/4",{
        	name:"dazhuang",
            age:99
        })
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
        })
        // 若失败走.catch
        .catch(err => {
        	console.log("err",err)
        })
    }
    
    • 使用patch请求方式(传参数):
    opatch.onclick = function() {
    	axios.patch("http://localhost:3000/users/4",{
            age:101
        })
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
        })
        // 若失败走.catch
        .catch(err => {
        	console.log("err",err)
        })
    }
    
    • 使用delete请求方式(无参数):
    odelete.onclick = function() {
    	axios.delete("http://localhost:3000/users/4")
        // 若成功走.then
        .then(res => {
        	console.log(res.data)
    	})
        // 若失败走.catch
        .catch(err => {
            console.log("err",err)
        })
    }
    
    • axios(config)配置:
    axios({
    	method:"post",
    	url:'http://localhost:3000/users',
    	// put post等放入data中 get放入params中
    	data:{
    		name:'kerwin',
    		age: 88
    	}
    })
    .then(res => {
    	console.log(res.data)
    })
    .catch(err => {
    	console.log(err)
    })
    

    4.2 axios使用

    4.2.1 axios拦截器

    • db.json代码:
    {
      "news": [
          { "id" : 1, "title" : "男人看了沉默,女人看了流泪", "author" : "kerwin"},
          { "id" : 2, "title" : "震惊!他年薪仅1元", "author" : "tiechui"},
          { "id" : 3, "title" : "速看!万分危急!", "author" : "gangdan"}
      ],
      "comments": [
          { "id" : 1, "body" : "我是男人", "newsId" : 1 },
          { "id" : 2, "body" : "我是女人", "newsId" : 1 },
          { "id" : 3, "body" : "我年薪2元", "newsId" : 2 },
          { "id" : 4, "body" : "我年薪3元", "newsId" : 2 },
          { "id" : 5, "body" : "1块钱就能买1块钱的东西", "newsId" : 3 },
          { "id" : 6, "body" : "2块钱就能买2块钱的东西", "newsId" : 3 }
      ]
    }
    
    • 01.html代码:
    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>Documenttitle>
        
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js">script>
    head>
    <body>
        <button id="get">getbutton>
        <script>
            var oget = document.querySelector("#get")
    
            // axios拦截器
            // request请求拦截器
            axios.interceptors.request.use(function (config) {
                // Do something before request is sent
                // console.log("loading-开始")
                console.log("loading显示....")
                return config;
            }, function (error) {
                // Do something with request error
                return Promise.reject(error);
            });
    
            // response响应拦截器
            // Add a response interceptor
            axios.interceptors.response.use(function (response) {
                // Any status code that lie within the range of 2xx cause this function to trigger
                // Do something with response data
                // 成功响应拦截器
                // console.log("loading-结束")
                console.log("成功-隐藏loading....")
                return response;
            }, function (error) {
                // Any status codes that falls outside the range of 2xx cause this function to trigger
                // Do something with response error
                // 失败响应拦截器
                // console.log("loading---结束")
                console.log("失败-隐藏loading....")
                return Promise.reject(error);
            });
    
            oget.onclick = function() {
                axios.get('http://localhost:3000/news').then(res => {
                    console.log(res.data);
                }).catch(err => {
                    console.log("err",err);
                })
            }
        script>
    body>
    html>
    

    在这里插入图片描述
    【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第5张图片

    4.2.2 axios中断器

    const controller = new AbortController();
    
    axios.get('/foo/bar', {
       signal: controller.signal
    }).then(function(response) {
       //...
    });
    // cancel the request
    controller.abort()
    
    • 01.html代码:
    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>Documenttitle>
        
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js">script>
    head>
    <body>
        <button id="get">getbutton>
        
        <button id="abort">abortbutton>
        <script>
            var oget = document.querySelector("#get")
            var oabort = document.querySelector("#abort")
    
            // axios拦截器
            // request请求拦截器
            axios.interceptors.request.use(function (config) {
                // Do something before request is sent
                // console.log("loading-开始")
                console.log("loading显示....")
                return config;
            }, function (error) {
                // Do something with request error
                return Promise.reject(error);
            });
    
            // response响应拦截器
            // Add a response interceptor
            axios.interceptors.response.use(function (response) {
                // Any status code that lie within the range of 2xx cause this function to trigger
                // Do something with response data
                // 成功响应拦截器
                // console.log("loading-结束")
                console.log("成功-隐藏loading....")
                return response;
            }, function (error) {
                // Any status codes that falls outside the range of 2xx cause this function to trigger
                // Do something with response error
                // 失败响应拦截器
                // console.log("loading---结束")
                console.log("失败-隐藏loading....")
                return Promise.reject(error);
            });
    
            // axios中断器
            const controller = new AbortController();
    
            oget.onclick = function() {
                axios.get('http://localhost:3000/news',{
                    signal: controller.signal
                })
                .then(res => {
                    console.log(res.data);
                }).catch(err => {
                    console.log("err",err);
                })
            }
    
            oabort.onclick = function() {
                controller.abort()
            }
        script>
    body>
    html>
    

    【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第6张图片

    5 同源策略

    • 一个URL有三部分组成:协议、域名(指向主机)、端口,只有这三个完全相同的 URL 才能称之为同源。
    • 如下,能和http://www.example.com/dir1/index.html 同源的是?
      【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第7张图片
    • 无法读取非同源网页的 Cookie、LocalStorage 。
    • 无法接触非同源网页的 DOM。
    • 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。
    • 注意:同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

    6 解决跨域

    6.1 jsonp

    • Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
    • 为什么我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )呢?这是因为同源策略。
    • 1.txt代码:
    test("xiaowang")
    
    • 01.html代码:
    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>Documenttitle>
    head>
    <body>
        <script>
            function test(data){
                console.log("111",data);
            }
    
    
            var oscript = document.createElement("script")
            oscript.src = "1.txt"
            document.body.appendChild(oscript)
    
            // 1.script标签没有跨域限制
            // 2.后端配合返回的是 函数() 调用的方式
            // 3.前端必须提前声明好这个函数
    
            // 缺点:jsonp只能get请求 无法post、put、delete
        script>
        
    body>
    html>
    

    在这里插入图片描述

    • 案例:
    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>Documenttitle>
    head>
    <body>
        <input type="text" id="search">
        <ul id="list">
    
        ul>
    
        <script>
            var osearch = document.querySelector('#search')
            var olist = document.querySelector('#list')
    
            osearch.oninput = function(){
                // console.log(osearch.value)
                if(osearch.value === "") {
                    olist.innerHTML = ""
                    return
                }
                var oscript = document.createElement("script")
                oscript.src = `https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=39646,39671,39663,39676,39678,39713,39791,39787,39704,39793,39681,39662&wd=${osearch.value}&req=2&csor=1&cb=test&_=1700639132336`
                document.body.appendChild(oscript)
    
                oscript.onload = function() {
                    oscript.remove() // 创建完script标签 等它load完了 就给它移掉
                }
            }
    
            function test(data) {
                // console.log(data.g);
                olist.innerHTML = data.g.map(item => 
                    `
                        
  • ${item.q}
  • `
    ).join("") }
    script> body> html>

    【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】_第8张图片

    6.2 其他技术手段

    • 加上响应头
    • 反向代理nginx跨域解决方案

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