前端指南Dom操作、Ajax请求以和跨域解决方案
DOM操作
- Document Object Model(文档对象模型)
- DOM 操作,可以简单理解成“元素操作”
具体DOM操作
-
更新:更新该DOM结点的内容,相当于更新了该DOM结点表示的HTML内容
-
遍历:遍历该DOM节点下的子节点,以便进行进一步操作
-
添加:在该DOM节点下新增一个子节点,相当于动态增加了一个HTML节点
-
删除:将该节点从HTML中删除,相当于删掉了该DOM节点的内容以及他包含的所有子节点
-
拿到这个DOM节点:
- document.getElementById()
- document.getElementsByTagName()
- CSS选择器document.getElementsByClassName()
- ID在HTML文档中是唯一的
更新DOM
- 一种是修改innerHTML属性,这个方式非常强大,不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树
- 用innerHTML时要注意,是否需要写入HTML。如果写入的字符串是通过网络拿到的,要注意对字符编码来避免XSS攻击
- 第二种是修改innerText或textContent属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标签
- 两者区别:两者的区别在于读取属性时,innerText不返回隐藏元素的文本,而textContent返回所有文本
插入DOM
- 如果DOM结点是空的:innerHTML = ‘child’,就可以修改DOM节点的内容,相当于“插入”了新的DOM节点
- 如果DOM结点不是空的:
- 一个是使用appendChild,把一个子节点添加到父节点的最后一个子节点
- 把<p id=“js”>JavaScript</p>添加到<div id=“list”>的最后一项
- 一个是使用appendChild,把一个子节点添加到父节点的最后一个子节点
var
js = document.getElementById('js'),
list = document.getElementById('list');
list.appendChild(js);
- parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前
删除DOM
- 删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置
- 要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉
Ajax
定义
- 什么是Ajax?
- 异步就按JavaScript和XML,是一种用于创建快速动态网页的技术,通过与服务器进行少量数据交换,Ajax可以使网页实现异步更新,这意味着可以在不重新加载整个页面的情况下,对网页的某部分进行更新
- 传统的网页-不使用Ajax如果需要更新内容,必须重新加载整个网页面
- 异步就按JavaScript和XML,是一种用于创建快速动态网页的技术,通过与服务器进行少量数据交换,Ajax可以使网页实现异步更新,这意味着可以在不重新加载整个页面的情况下,对网页的某部分进行更新
- 同步与异步的区别
- 同步提交:当用户发送请求时,当前网页不可以使用,服务器响应页面到客户端,相应完成,用户才可以使用页面
- 异步提交:当用户发送请求时,当前页面还可以继续使用,当一部请求的数据响应给页面,页面把数据显示出来
- Ajax工作原理
- 客户端发送请求,请求交给xhr
- xhr把请求提交给服务器,服务期进行业务处理,
- 服务器响应数据交给xhr对象
- xhr对象接收数据,由JavaScript把数据写到页面上
实现Ajax的基本步骤-异步调用和局部刷新
- 创建XMLHttpRequest对象,即创建一个异步调用对象
- 创建一个新的HTTP请求,并制定该HTTP请求、URL及验证信息
- 设置响应HTTP请求状态变化的函数
- 发送HTTP请求
- 获取异步调用返回的数据
- 使用JavaScript和DOM实现局部刷新
代码中的参数解释如下所示:
- method:该参数用于指定HTTP的请求方法,一共有get、post、head、put、delete五种方法,常用的方法为get和post
- URL:该参数用于指定HTTP请求的URL地址,可以是绝对URL,也可以是相对URL
- flag:该参数为可选,参数值为布尔型。该参数用于指定是否使用异步方式。true表示异步、false表示同步,默认为true
- name:该参数为可选参数,用于输入用户名。如果服务器需要验证,则必须使用该参数
- password:该参数为可选,用于输入密码。若服务器需要验证,则必须使用该参数
注意:如果HTML文件放在Web服务器上,在Netscape浏览器中的JavaScript安全机制不允许与本机之外的主机进行通信。也就是说,使用open()方法只能打开与HTML文件在同一个服务器上的文件。而在IE浏览器中则无此限制(虽然可以打开其他服务器上的文件,但也会有警告提示)
- 未初始化状态。在创建完XMLHttpRequest对象时,该对象处于未初始化状态,此时XMLHttpRequest对象的readyState属性值为0
- 初始化状态。在创建完XMLHttpRequest对象后使用open()方法创建了HTTP请求时,该对象处于初始化状态。此时XMLHttpRequest对象的readyState属性值为1
- 发送数据状态。在初始化XMLHttpRequest对象后,使用send()方法发送数据时,该对象处于发送数据状态,此时XMLHttpRequest对象的readyState属性值为2
- 接收数据状态。Web服务器接收完数据并进行处理完毕之后,向客户端传送返回的结果。此时,XMLHttpRequest对象处于接收数据状态,XMLHttpRequest对象的readyState属性值为3
- 完成状态。XMLHttpRequest对象接收数据完毕后,进入完成状态,此时XMLHttpRequest对象的readyState属性值为4。此时接收完毕后的数据存入在客户端计算机的内存中,可以使用responseText属性或responseXml属性来获取数据
完整Ajax实例
<html>
<head>
<title>AJAX实例</title>
<script language="javascript" type="text/javascript">
function ajaxHttpRequestFunc(){
let xmlHttpRequest; // 创建XMLHttpRequest对象,即一个用于保存异步调用对象的变量
if(window.ActiveXObject){ // IE浏览器的创建方式
xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){ // Netscape浏览器中的创建方式
xmlHttpRequest = new XMLHttpRequest();
}
xmlHttpRequest.onreadystatechange=function(){ // 设置响应http请求状态变化的事件
console.log('请求过程', xmlHttpRequest.readyState);
if(xmlHttpRequest.readyState == 4){ // 判断异步调用是否成功,若成功开始局部更新数据
console.log('状态码为', xmlHttpRequest.status);
if(xmlHttpRequest.status == 200) {
console.log('异步调用返回的数据为:', xmlHttpRequest .responseText);
document.getElementById("myDiv").innerHTML = xmlHttpRequest .responseText; // 局部刷新数据到页面
} else { // 如果异步调用未成功,弹出警告框,并显示错误状态码
alert("error:HTTP状态码为:" xmlHttpRequest.status);
}
}
}
xmlHttpRequest.open("GET","https://www.runoob.com/try/ajax/ajax_info.txt",true); // 创建http请求,并指定请求得方法(get)、url(https://www.runoob.com/try/ajax/ajax_info.txt)以及验证信息
xmlHttpRequest.send(null); // 发送请求
}
</script>
</head>
<body>
<div id="myDiv">原数据</div>
<input type = "button" value = "更新数据" onclick = "ajaxHttpRequestFunc()">
</body>
</html>
常见的前端跨域解决方案
什么是跨域?
- 跨域是指浏览器允许向服务器发送跨域请求, 从而克服Ajax只能同源使用的限制
什么是同源策略?
- 一种约定,指“协议 域名 端口”三者相同,即使两个不同的域名指向同一个IP地址,也非同源
- 同源限制以下操作:
- cookie、localStorage和indexDB无法获取
- DOM和JS对象无法获取
- AJAX请求不能发送
常见跨域场景
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.domain.com/a.js http://www.domain.com/b.js http://www.domain.com/lab/c.js |
同一域名,不同文件或路径 | 允许 |
http://www.domain.com:8000/a.js http://www.domain.com/b.js |
同一域名,不同端口 | 不允许 |
http://www.domain.com/a.js https://www.domain.com/b.js |
同一域名,不同协议 | 不允许 |
http://www.domain.com/a.js http://192.168.4.12/b.js |
域名和域名对应相同ip | 不允许 |
http://www.domain.com/a.js http://x.domain.com/b.js http://domain.com/c.js |
主域相同,子域不同 | 不允许 |
http://www.domain1.com/a.js http://www.domain2.com/b.js |
不同域名 | 不允许 |
六种跨域解决方案
JONSP跨域
原理:利用script标签没有跨域限制,通过script标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据
- 原生JS实现
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
服务端返回如下:
handleCallback({“success”: true, “user”: “admin”})
- jQuery Ajax实现:
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
- Vue axios实现
this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
- jsonp缺点:只能发送get请求
跨域资源共享CORS
- 允许浏览器向跨源服务器,发出XMLHTTPRequest请求,从而克服了Ajax只能同源使用的限制,CORS需要浏览器和服务器同时支持
- 只要同时满足以下两个条件,就属于简单请求
- 使用下列方法之一
- head
- get
- post
- 请求的header是
- Accept
- Accept-Language
- Content-Language
- Content-Type:只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain
- 不同时满足上面两个条件,就属于非简单请求
- 使用下列方法之一
response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
Nginx代理跨域
- 通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段
www.百度.com/index.html
需要调用www.sina.com/server.php
,可以写一个接口www.百度.com/server.php
,由这个接口在后端去调用www.sina.com/server.php
并拿到返回值,然后再返回给index.html
document.domain
- 主要解决:window之间不能交互操作的跨域情况,且只能适用于主域相同子域不同的情况
- 优点:可以实现不同window之间的相互访问和操作
- 缺点:
- 只适用于window之间的通信,不能用于xhr
- 只能在主域相同且子域不同的情况下使用
- 步骤:
- 在1页面中设置主域
- 在2页面中设置主域
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//设置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
}
</script>
<script type="text/javascript">
document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>
window.name
- 关键点:
window.name
在页面的生命周期中共享一个window.name
- 优点:
- 最简单的利用了浏览器的特性来做到不同域之间的数据传递
- 不需要前端和后端的特殊配置
- 缺点:
- 大小限制:window.name最大size是2M左右,不同浏览器中会有不同约定
- 安全性:页面所有window都可以修改,不安全
- 数据类型:限于字符串,如果是对象或者其他会自动被转化为字符串
- 使用方式:直接修改window.name即可
postMessage
- 关键点:通过
window.postMessage
的方式进行使用,并可以监听其发送的消息 - 优点:不需要后端介入就可以做到跨域,一个函数外加两个参数(请求url, 发送数据)就可以搞定;移动端兼容性好
- 缺点:无法做到一对一的传递方式:发出消息相当于一个广播的过程,该页面总有onmessage都会受到,所以需要做到消息的判断
- 安全性问题:
- 三方可以通过截获,注入html或者脚本的形式监听到消息,从而到达篡改的效果,一定要做好相关限制
- 发送的数据会通过结构化克隆算法进行序列化,只有满足该算法要求的算法才能够被解析,否则会报错
- 使用方式:通信的函数,sendMessage负责发送消息,bindEvent负责消息的监听并处理
Storage.prototype.sendMessage_=function(type,params,fn){
if(this.topWindow){
this.handleCookie_(type,params,fn);
return;
}
var eventId = this.addToQueue_(fn,type);
var storageIframe = document.getElementById('mip-storage-iframe');
var element = document.createElement("a");
element.href = this.origin;
var origin = element.href.slice(0,element.href.indexOf(element.pathname) 1);
storageIframe.contentWindow.postMessage({
type:type,
params:params,
eventId:eventId
},origin);
}
Storage.prototype.bindEvent_=function(){
window.onmessage = function(res){
//判断消息来源
if(window == res.source.window.parent &&
res.data.type === this.messageType.RES &&
window.location.href.match(res.origin.host).length >0){
var fn = this.eventQueue[res.data.eventId];
fn && fn();
delete this.eventQueue[res.data.eventId];
var isEmpty = true;
for(var t in this.eventQueue){
isEmpty = false;
}
if(isEmpty){
this.id = 0;
}
}
}.bind(this);
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgchjih
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01