【初始前后端交互+原生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 ~ 2992. 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 了
四、responseTextajax 对象中的 `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>Document</title>
</head>
<body><button>aaa</button><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"
}

在这里插入图片描述

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>Document</title>
</head>
<body><button id="btn">click</button><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 `<li><img src="${item.imageUrl}"/><div>${item.name}</div>    </li>`})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监视:
    在这里插入图片描述

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" // 方式一bodybody: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" // 方式一bodybody: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" // 方式一bodybody: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)})
}

在这里插入图片描述

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>Document</title>
</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].titlereturn 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 => `<li>${item.body}</li>`).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>Document</title>
</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 resultif(res.length > 0) {otitle.innerHTML = res[0].titleresult = 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 => `<li>${item.body}</li>`).join("") // join是为了避免中间有逗号}</script>
</body>
</html>

在这里插入图片描述

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>Document</title><!-- 引入axios --><script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
</head>
<body><button id="get">get</button><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 errorreturn Promise.reject(error);});// response响应拦截器// Add a response interceptoraxios.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>

在这里插入图片描述
在这里插入图片描述

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>Document</title><!-- 引入axios --><script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
</head>
<body><button id="get">get</button><!-- 终止按钮 --><button id="abort">abort</button><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 errorreturn Promise.reject(error);});// response响应拦截器// Add a response interceptoraxios.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>

在这里插入图片描述

5 同源策略

  • 一个URL有三部分组成:协议、域名(指向主机)、端口,只有这三个完全相同的 URL 才能称之为同源。
  • 如下,能和http://www.example.com/dir1/index.html 同源的是?
    在这里插入图片描述
  • 无法读取非同源网页的 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>Document</title>
</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><!-- <script>// <script src="1.txt">// test("xiaowang")</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>Document</title>
</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 => `<li>${item.q}</li>`).join("")}</script>
</body>
</html>

在这里插入图片描述

6.2 其他技术手段

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭配:基于OpenCV的边缘检测实战

引言 计算机中的目标检测与人类识别物体的方式相似。作为人类&#xff0c;我们可以分辨出狗的形象&#xff0c;因为狗的特征是独特的。尾巴、形状、鼻子、舌头等特征综合在一起&#xff0c;帮助我们把狗和牛区分开来。 同样&#xff0c;计算机能够通过检测与估计物体的结构和性…

Linux 常见命令篇

history 获取执行的指令记录 语法格式: history [参数] 常用参数&#xff1a; -a 写入命令记录 -c 清空命令记录 -d 删除指定序号的命令记录 -n 读取命令记录 -r 读取命令记录到缓冲区 -s 将指定的命令添加到缓冲区 -w 将缓冲区信息写入到历史文件 history#获取最近的三条…

C#关键字、特性基础及扩展合集(持续更新)

一、基础 Ⅰ 关键字 1、record record&#xff08;记录&#xff09;&#xff0c;编译器会在后台创建一个类。支持类似于结构的值定义&#xff0c;但被实现为一个类&#xff0c;方便创建不可变类型&#xff0c;成员在初始化后不能再被改变 &#xff08;C#9新增&#xff09; …

Hologres性能优化指南1:行存,列存,行列共存

在Hologres中支持行存、列存和行列共存三种存储格式&#xff0c;不同的存储格式适用于不同的场景。 在建表时通过设置orientation属性指定表的存储格式&#xff1a; BEGIN; CREATE TABLE <table_name> (...); call set_table_property(<table_name>, orientation,…

Centos上安装Docker和DockerCompose

安装Docker Docker可以运行在MAC&#xff0c;Windows&#xff0c;CtenOS,UBUNTU等操作系统上。目前主流的版本有Docker CE和Docker EE&#xff0c;CE是免费的开源Docker版本&#xff0c;适用于开发人员和小型团队&#xff0c;EE是适用于企业的容器化解决方案。它基于Docker CE…

2023-11-24 LeetCode每日一题(统计和小于目标的下标对数目)

2023-11-24每日一题 一、题目编号 2824. 统计和小于目标的下标对数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target &#xff0c;请你返回满足 0 < i < j < n 且 nums[i] nums[j] < targe…

开源的文本编辑器Notepad++ 8.6.0版本在Windows系统上的下载与安装配置

目录 前言一、Notepad 安装二、使用配置总结 前言 Notepad 是一款简单而强大的文本编辑工具&#xff0c;通常用于快速创建和编辑文本文件。以下是 Notepad 工具的详细介绍。注&#xff1a;文末附有下载链接&#xff01; 主要特点&#xff1a; ——简洁易用&#xff1a; Note…

蓝桥杯物联网竞赛_STM32L071_4_按键控制

原理图&#xff1a; 当按键S1按下PC14接GND&#xff0c;为低电平 CubMX配置: Keil配置&#xff1a; main函数&#xff1a; while (1){/* USER CODE END WHILE */OLED_ShowString(32, 0, "hello", 16);if(Function_KEY_S1Check() 1){ OLED_ShowString(16, 2, &quo…

FANUC机器人到达某个点位时,为什么不显示@符号?

FANUC机器人到达某个点位时,为什么不显示@符号? 该功能由变量$MNDSP_POSCF = 0(不显示)/1(显示)/2(光标移动该行显示) 控制,该变量设置为不同的值,则启用对应的功能。 如下图所示,为该变量设置不同的值时的对比, 其他常用的系统变量可参考以下内容: 在R寄存器指定速度…

什么是AWS CodeWhisperer?

AWS CodeWhisperer https://aws.amazon.com/cn/codewhisperer/ CodeWhisperer 经过数十亿行代码的训练&#xff0c;可以根据您的评论和现有代码实时生成从代码片段到全函数的代码建议。 ✔ 为您量身定制的实时 AI 代码生成器 ✔ 支持热门编程语言和 IDE ✔ 针对 AWS 服务的优…

java设计模式学习之【工厂模式】

文章目录 引言工厂方法模式简介定义与用途&#xff1a;实现方式&#xff1a; 使用场景优势与劣势工厂模式在spring中的应用电费计算示例&#xff08;简单工厂模式&#xff09;改善为方法工厂模式代码地址 引言 在软件开发的世界中&#xff0c;对象的创建可能是一个复杂且重复的…

网安融合新进展:Check Point+七云网络联合研发,加固大型企业边缘、分支侧安全

AI 爆火、万物互联&#xff0c;底层需要更灵活的网络设施提供支撑。据国际分析机构 Gartner 预测&#xff0c;到 2024 年&#xff0c;SD-WAN&#xff08;软件定义的广域网&#xff09;使用率将达到 60%。不过边缘和终端兴起&#xff0c;未经过数据中心的流量也在成为新的安全风…

Spring Boot Actuator 2.2.5 基本使用

1. pom文件 &#xff0c;添加 Actuator 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 2.application.properties 文件中添加以下配置 …

LLMLingua:集成LlamaIndex,对提示进行压缩,提供大语言模型的高效推理

大型语言模型(llm)的出现刺激了多个领域的创新。但是在思维链(CoT)提示和情境学习(ICL)等策略的驱动下&#xff0c;提示的复杂性不断增加&#xff0c;这给计算带来了挑战。这些冗长的提示需要大量的资源来进行推理&#xff0c;因此需要高效的解决方案&#xff0c;本文将介绍LLM…

MATLAB实战 | MEX文件

应用接口是MATLAB与其他语言相互调用各自函数的方法&#xff0c;MEX文件使MATLAB程序中可以调用或链接其他语言编写的函数&#xff0c;而MATLAB引擎使其他语言程序中可以调用MATLAB函数。 01、MEX文件 MEX是MATLAB Executable的缩写&#xff0c;是MATLAB中用于调用其他语言编写…

Leetcode103 二叉树的锯齿形层序遍历

二叉树的锯齿形层序遍历 题解1 层序遍历双向队列 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。 提示&#xff1a…

【计算机网络】(网络层)定长掩码和变长掩码

目录 1、IPV4地址的应用规划 2、例题分析 2.1、定长的子网掩码 2.2、变长的子网掩码 1、IPV4地址的应用规划 定长的子网掩码&#xff08;FLSM&#xff09;&#xff1a; 使用同一个子网掩码划分子网&#xff0c;每个子网所分配的IP地址数量相同&#xff0c;造成IP地址的浪费…

腾讯云发布新一代基于AMD处理器的星星海云服务器实例SA5

基础设施的硬实力&#xff0c;愈发成为云厂商的核心竞争力。 11月24日&#xff0c;腾讯云发布了全新一代星星海服务器。基于自研服务器的高密设计与硬件升级&#xff0c;对应云服务器SA5是全球首家搭载第四代AMD EPYC处理器&#xff08;Bergamo&#xff09;的公有云实例&#…

京东数据分析:2023年10月京东彩妆销售大数据采集

鲸参谋监测的京东平台10月份彩妆市场销售数据已出炉&#xff01; 鲸参谋数据显示&#xff0c;今年10月份&#xff0c;京东平台上彩妆市场的销量将近430万&#xff0c;环比增长约21%&#xff0c;同比下滑约3%&#xff1b;销售额将近5.8亿&#xff0c;环比增长约7%&#xff0c;同…

web静态网页设计与制作-基于HTML+CSS+JS实现旅游摄影网站

web静态网页设计与制作&#xff0c;基于HTMLCSSJS实现精美的旅游摄影网站&#xff0c;拥有极简的设计风格&#xff0c;丰富的交互动效&#xff0c;让人眼前一亮&#xff0c;享受视觉上的体验。 我使用了基本的HTML结构来构建网页&#xff0c;并使用CSS样式进行美化设计&#xf…