【前端指南】Dom操作、Ajax请求以及跨域解决方案

文章目录

      • DOM操作
        • 具体DOM操作
          • 更新DOM
          • 插入DOM
          • 删除DOM
      • Ajax
        • 定义
        • 实现Ajax的基本步骤-异步调用和局部刷新
        • 完整Ajax实例
      • 常见的前端跨域解决方案
        • 什么是跨域?
          • 什么是同源策略?
          • 常见跨域场景
          • 六种跨域解决方案
            • JONSP跨域
            • 跨域资源共享CORS
            • Nginx代理跨域
            • document.domain
            • window.name
            • postMessage

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,把一个子节点添加到父节点的最后一个子节点
      • JavaScript

        添加到
        的最后一项
var
    js = document.getElementById('js'),
    list = document.getElementById('list');
list.appendChild(js);
  • parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前
删除DOM
  • 删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置
  • 要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉

Ajax

定义

  1. 什么是Ajax?
    • 异步就按JavaScript和XML,是一种用于创建快速动态网页的技术,通过与服务器进行少量数据交换,Ajax可以使网页实现异步更新,这意味着可以在不重新加载整个页面的情况下,对网页的某部分进行更新
      • 传统的网页-不使用Ajax如果需要更新内容,必须重新加载整个网页面
  2. 同步与异步的区别
  • 同步提交:当用户发送请求时,当前网页不可以使用,服务器响应页面到客户端,相应完成,用户才可以使用页面
  • 异步提交:当用户发送请求时,当前页面还可以继续使用,当一部请求的数据响应给页面,页面把数据显示出来
  1. Ajax工作原理
  • 客户端发送请求,请求交给xhr
  • xhr把请求提交给服务器,服务期进行业务处理,
  • 服务器响应数据交给xhr对象
  • xhr对象接收数据,由JavaScript把数据写到页面上

实现Ajax的基本步骤-异步调用和局部刷新

  1. 创建XMLHttpRequest对象,即创建一个异步调用对象
  2. 创建一个新的HTTP请求,并制定该HTTP请求、URL及验证信息
  3. 设置响应HTTP请求状态变化的函数
  4. 发送HTTP请求
  5. 获取异步调用返回的数据
  6. 使用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浏览器中则无此限制(虽然可以打开其他服务器上的文件,但也会有警告提示)

  1. 未初始化状态。在创建完XMLHttpRequest对象时,该对象处于未初始化状态,此时XMLHttpRequest对象的readyState属性值为0
  2. 初始化状态。在创建完XMLHttpRequest对象后使用open()方法创建了HTTP请求时,该对象处于初始化状态。此时XMLHttpRequest对象的readyState属性值为1
  3. 发送数据状态。在初始化XMLHttpRequest对象后,使用send()方法发送数据时,该对象处于发送数据状态,此时XMLHttpRequest对象的readyState属性值为2
  4. 接收数据状态。Web服务器接收完数据并进行处理完毕之后,向客户端传送返回的结果。此时,XMLHttpRequest对象处于接收数据状态,XMLHttpRequest对象的readyState属性值为3
  5. 完成状态。XMLHttpRequest对象接收数据完毕后,进入完成状态,此时XMLHttpRequest对象的readyState属性值为4。此时接收完毕后的数据存入在客户端计算机的内存中,可以使用responseText属性或responseXml属性来获取数据

完整Ajax实例



AJAX实例



    
原数据

常见的前端跨域解决方案

什么是跨域?

  • 跨域是指浏览器允许向服务器发送跨域请求, 从而克服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函数返回的数据

  1. 原生JS实现
 

服务端返回如下:
handleCallback({“success”: true, “user”: “admin”})

  1. jQuery Ajax实现:
$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",  // 自定义回调函数名
    data: {}
});
  1. 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需要浏览器和服务器同时支持
  • 只要同时满足以下两个条件,就属于简单请求
    1. 使用下列方法之一
      • head
      • get
      • post
    2. 请求的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.baidu.com/index.html需要调用www.sina.com/server.php,可以写一个接口www.baidu.com/server.php,由这个接口在后端去调用www.sina.com/server.php并拿到返回值,然后再返回给index.html
document.domain
  • 主要解决:window之间不能交互操作的跨域情况,且只能适用于主域相同子域不同的情况
  • 优点:可以实现不同window之间的相互访问和操作
  • 缺点:
    • 只适用于window之间的通信,不能用于xhr
    • 只能在主域相同且子域不同的情况下使用
  • 步骤:
    1. 在1页面中设置主域
    2. 在2页面中设置主域



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

你可能感兴趣的:(专业技能基础,#,前端指南,1024程序员节,DOM操作,Ajax,前端,跨域)