1.DOM
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。
节点
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
节点的类型有七种:
-
Document
:整个文档树的顶层节点 -
DocumentType
:doctype
标签(比如<!DOCTYPE html>
) -
Element
:网页的各种HTML标签(比如<body>
、<a>
等) -
Attr
:网页元素的属性(比如class="right"
) -
Text
:标签之间或标签包含的文本 -
Comment
:注释 -
DocumentFragment
:文档的片段
node接口属性
不同节点的nodeType
属性值和对应的常量如下:
- 文档节点(document):9,对应常量
Node.DOCUMENT_NODE
- 元素节点(element):1,对应常量
Node.ELEMENT_NODE
- 属性节点(attr):2,对应常量
Node.ATTRIBUTE_NODE
- 文本节点(text):3,对应常量
Node.TEXT_NODE
- 文档片断节点(DocumentFragment):11,对应常量
Node.DOCUMENT_FRAGMENT_NODE
- 文档类型节点(DocumentType):10,对应常量
Node.DOCUMENT_TYPE_NODE
- 注释节点(Comment):8,对应常量
Node.COMMENT_NODE
确定节点类型时,使用nodeType
属性是常用方法。
2.Element 节点
元素节点的nodeType
属性都是1
var p = document.querySelector('p');
console.info(p.nodeName) // "p"
console.info(p.nodeType) // 1(元素节点的属性为1)
Element.id
属性返回指定元素的id
属性,该属性可读写
// HTML 代码为 <p id="foo">
var p = document.querySelector('p');
console.info(p.id) // "foo" id属性的值大小写敏感,浏览器能正确识别<p id="foo">和<p id="FOO">这两个元素的id属性
Element.tagName
Element.tagName
属性返回指定元素的大写标签名,与nodeName
属性的值相等。
// HTML代码为 <span id="myspan">Hello</span>
var span = document.getElementById('myspan');
console.info(span.id) //"myspan"
console.info(span.tagName) // "SPAN"
Element.attributes
Element.attributes
属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点
js类似数组的对:正常的数组,没有length属性。而我们类似数组的对象,它实现了数组的方法,但是它比数组多了一个属性,就是length
var p = document.querySelector('p');
var attrs = p.attributes;
console.info(attrs);
for (var i = attrs.length - 1; i >= 0; i--) {
console.log(attrs[i].name + '->' + attrs[i].value);
}
Element.innerHTML
Element.innerHTML
属性返回一个字符串,等同于该元素包含的所有 HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括<HTML>
和<body>
元素。
如果将innerHTML
属性设为空,等于删除所有它包含的所有节点。
el.innerHTML = ''; 将el节点变成了一个空节点,el原来包含的节点被全部删除
注意,读取属性值的时候,如果文本节点包含&
、小于号(<
)和大于号(>
),innerHTML
属性会将它们转为实体形式&
、<
、>
。如果想得到原文,建议使用element.textContent
属性。
<p id="p" name="p1" class="p2">5>3</p>
var p=document.getElementById('p')
console.info(p.innerHTML); //5>3
如果文本之中含有<script>
标签,虽然可以生成script
节点,但是插入的代码不会执行。
var name = "<script>alert('haha')</script>";
el.innerHTML = name;
var el=document.getElementById('p')
var name="<svg οnlοad=alert(1)>";
el.textContent=name; //<svg οnlοad=alert(1)>
上面代码中,alert
方法是会执行的。因此为了安全考虑,如果插入的是文本,最好用textContent
属性代替innerHTML
。
Element.getElementsByClassName()
Element.getElementsByClassName
方法返回一个HTMLCollection
实例,成员是当前元素节点的所有具有指定 class 的子元素节点。该方法与document.getElementsByClassName
方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
var element = document.getElementById('example'); 单个元素
var matches = element.getElementsByClassName('foo'); 数组
Element.getElementsByTagName()(抓元素名称)
Element.getElementsByTagName()
方法返回一个HTMLCollection
实例,成员是当前节点的所有匹配指定标签名的子元素节点。该方法与document.getElementsByClassName()
方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
注意,该方法的参数是大小写不敏感的,因为 HTML 标签名也是大小写不敏感。
js严格区分大小写
Element.focus(),Element.blur()
Element.focus
方法用于将当前页面的焦点,转移到指定元素上。
<input type="text" id="demo">
document.getElementById('demo').focus();
无需点击,直接聚焦
Element.click()
<p id="demo" onclick="alert(1)">aaa</p>
document.getElementById('demo').click();
上述代码中,点击aaa,会出现弹窗
2.node
Node.prototype.insertBefore()
insertBefore
方法用于将某个节点插入父节点内部的指定位置。
var insertedNode = parentNode.insertBefore(newNode,referenceNode);
insertBefore
方法接受两个参数,第一个参数是所要插入的节点newNode
,第二个参数是父节点parentNode
内部的一个子节点referenceNode
。newNode
将插在referenceNode
这个子节点的前面。返回值是插入的新节点newNode
。
var p =document.createElement('p');
p.innerText='ppp';
document.body.insertBefore(p,document.body.firstChild);
上述代码中,新建一个<p>
节点,插在document.body.firstChild
的前面,也就是成为document.body
的第一个子节点。
让雨果第二个参数为null,则新节点将插在当前节点内部的最后位置,即变成最后一个子节点。则上述代码运行顺序为a b ppp
Node.prototype.replaceChild()
replaceChild
方法用于将一个新的节点,替换当前节点的某一个子节点。
var replacedNode = parentNode.replaceChild(newChild, oldChild);
上述代码中,用新节点替换掉旧节点
var div = document.getElementById('example');
var span = document.createElement('span');
span.textContent = 'Hello World!'; div.parentNode.replaceChild(span,div); hello world 替换掉div内的内容
3.鼠标事件
移动事件
mousemove
:当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次。mouseenter
:鼠标进入一个节点时触发,进入子节点不会触发这个事件mouseover
:鼠标进入一个节点时触发,进入子节点会再一次触发这个事件(建议使用)
mouseover
事件和mouseenter
事件,都是鼠标进入一个节点时触发。两者的区别是,mouseenter
事件只触发一次,而只要鼠标在节点内部移动,mouseover
事件会在子节点上触发多次。
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
var ul = document.querySelector('ul');
// 进入 ul 节点以后,mouseenter 事件只会触发一次
// 以后只要鼠标在节点内移动,都不会再触发这个事件
// event.target 是 ul 节点
ul.addEventListener('mouseenter', function (event) {
event.target.style.color = 'purple';
setTimeout(function () {
event.target.style.color = ''; 第一个参数,既可以一个字符串,也可以执行一个函数
}, 500); 第二个参数,延迟多少秒执行
}, false); 监听事件的false
// 进入 ul 节点以后,只要在子节点上移动,mouseover 事件会触发多次
// event.target 是 li 节点
ul.addEventListener('mouseover', function (event) {
event.target.style.color = 'orange';
setTimeout(function () {
event.target.style.color = '';
}, 500);
}, false);
4.XMLHttpRequest 对象
$_REQUEST可以接收get、post、request三种传参方式
XMLHttpRequest
本身是一个构造函数,可以使用new
命令生成实例。它没有任何参数。
var xhr = new XMLHttpRequest();
注意,AJAX 只能向同源网址(协议、域名、端口都相同)发出 HTTP 请求,如果发出跨域请求,就会报错
下面是XMLHttpRequest
对象简单用法的完整例子
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
// 通信成功时,状态值为4
if (xhr.readyState === 4){ 标准状态,成功时是4
if (xhr.status === 200){
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
xhr.open('GET', '/endpoint', true); GET传递的方式 /endpoint传递的路径 ture看是不是异步
xhr.send(null); send传递什么值过去
上面代码中,send()的参数为null,表示发送请求的时候,不带有数据体。如果发送的是 POST 请求,这里就需要指定数据体。
一旦拿到服务器返回的数据,AJAX 不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在做的事情。
XMLHttpRequest.responseType
- “”(空字符串):等同于
text
,表示服务器返回文本数据。 - “arraybuffer”:ArrayBuffer 对象,表示服务器返回二进制数组。
- “blob”:Blob 对象,表示服务器返回二进制对象。
- “document”:Document 对象,表示服务器返回一个文档对象。
- “json”:JSON 对象。
- “text”:字符串
XMLHttpRequest.response (只读)
XMLHttpRequest.responseType(可写,在调用open()方法之后,send()方法之前)-----responseType设字符串为空时(等同于默认值text)
blob
类型适合读取二进制数据,比如图片文件
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'blob'; 前边为图片,使用blod(设置二进制返回值)
如果将这个属性设为ArrayBuffer
,就可以按照数组的方式处理二进制数据
事件监听属性
XMLHttpRequest 对象可以对以下事件指定监听函数。
- XMLHttpRequest.onloadstart:loadstart 事件(HTTP 请求发出)的监听函数
- XMLHttpRequest.onprogress:progress事件(正在发送和加载数据)的监听函数
- XMLHttpRequest.onabort:abort 事件(请求中止,比如用户调用了
abort()
方法)的监听函数 - XMLHttpRequest.onerror:error 事件(请求失败)的监听函数
- XMLHttpRequest.onload:load 事件(请求成功完成)的监听函数
- XMLHttpRequest.ontimeout:timeout 事件(用户指定的时限超过了,请求还未完成)的监听函数
- XMLHttpRequest.onloadend:loadend 事件(请求完成,不管成功或失败)的监听函数
XMLHttpRequest.withCredentials
XMLHttpRequest.withCredentials
属性是一个布尔值,表示跨域请求时,用户信息(比如 Cookie 和认证的 HTTP 头信息)是否会包含在请求之中,默认为false
,即向example.com
发出跨域请求时,不会发送example.com
设置在本机上的 Cookie(如果有的话)。
如果需要跨域 AJAX 请求发送 Cookie,需要withCredentials
属性设为true
( Cookie与withCredentials两个同时存在才可),同源的请求不需要设置这个属性。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
为了让这个属性生效,服务器必须显式返回Access-Control-Allow-Credentials
这个头信息。
Access-Control-Allow-Credentials: true
5.cors通信
CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨域的服务器,发出XMLHttpRequest
请求,从而克服了 AJAX 只能同源使用的限制。
简单请求
(1)请求方法是以下三种方法之一。
- HEAD
- GET
- POST
(2)HTTP 的头信息不超出以下几种字段。
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
基本流程
对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个Origin
字段。
GET /cors HTTP/1.1
Origin: http://api.bob.com 是简单请求,就自动在头信息中,添加一个origin字段
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
origin字段用来说明,本次请求来自哪个域(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果Origin
指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin(重要)
该字段是必须的。它的值要么是请求时Origin
字段的值,要么是一个*
,表示接受任意域名的请求。
Access-Control-Allow-Credential
该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中。设为true
,即表示服务器明确许可,浏览器可以把 Cookie 包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送 Cookie,不发送该字段即可。
Access-Control-Expose-Headers
该字段可选。CORS 请求时,XMLHttpRequest
对象的getResponseHeader()
方法只能拿到6个服务器返回的基本字段:Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
。如果想拿到其他字段,就必须在Access-Control-Expose-Headers
里面指定。上面的例子指定,getResponseHeader('FooBar')
可以返回FooBar
字段的值。
var xhr=new XMLHttpRequest();{
var url='http://127.0.0.1/test/ww.hph';
xhr.onload=function(){
if(xhr.readyState===4){
if(xhr.status===200){}
console.log(xhr.responseText);
}else{
console.error(xhr.statusText);
}
}
};
xhr.open=('GET',url,ture);
xhr.send(null);
<?php
header('Access-Control-Allow-Origin:http:192.168.189.131');
$username=$_POST['username'];
$password=$_POST['password'];
echo 'wang pei ting';
CORS 与 JSONP 的使用目的相同,但是比 JSONP 更强大。JSONP 只支持GET
请求,CORS 支持所有类型的 HTTP 请求。JSONP 的优势在于支持老式浏览器,以及可以向不支持 CORS 的网站请求数据。