零js基礎 | 程序設計 | 11 - DOM扩展
DOM扩展
var div = document.querySelector('#div')
//返回NodeList實例
var div = document.querySelectorAll('.divClass')
console.log(div.item(0))
console.log(div[0])
console.log(div)
matchesSelector(CSS選擇符),如果匹配 true,否則 false
if (matchesSelector(div[0], '#div.divClass')) {
alert(true)
}
//兼容性
function matchesSelector(element, selector) {
if (element.matchesSelector) {
return element.matchesSelector(selector);
} else if (element.msMatchesSelector) {
return element.msMatchesSelector(selector);
} else if (element.mozMatchesSelector) {
return element.mozMatchesSelector(selector);
} else if (element.webkitMatchesSelector) {
return element.webkitMatchesSelector(selector);
} else {
throw new Error("Not supported.");
}
}
支持Element Traversal 规范的浏览器有IE 9+、Firefox 3.5+、Safari 4+、Chrome 和Opera 10+。
childElementCount:返回子元素(不包括文本节点和注释)的个数。
firstElementChild:指向第一个子元素;firstChild 的元素版。
lastElementChild:指向最后一个子元素;lastChild 的元素版。
previousElementSibling:指向前一个同辈元素;previousSibling 的元素版。
nextElementSibling:指向后一个同辈元素;nextSibling 的元素版。
二、困扰你我的NodeList与HTMLCollection
相同点:1. 类数组。有length属性,可以用下标索引来访问其中的元素,但没有Array的slice等方法;
2. 只读。无法增删其中的元素;
3. 实时同步DOM树的变化。若DOM树有新元素加入,该类型的对象也会将新元素包含进来;
4. 可通过下标数字类型索引获取集合中指定位置的元素;
5. 可通过item({String | Number} 索引)方法获取集合中指定位置的元素,若通过索引找不到元素,则以第一个元素作为返回值。
不同点(主要表现在HTMLCollection比NodeList能力更强大):
1. HTMLCollection对象可通过namedItem({String} id或name)获取首个匹配的元素,若没有则返回null;
2. HTMLCollection对象可通过点方式获取第个id或name匹配的元素,若没有则返回undefined。
各浏览器选择器返回类型差别:
console.log(div instanceof NodeList) //true
//帶有.divClass.username的元素
var div = document.getElementsByClassName('divClass username')
console.log(div)
console.log(div instanceof HTMLCollection) //true;
傳統刪class
var classNames = div.className.split(/\s+/);
var pos = -1;
for(var i=0;i<classNames.length;i++){
if(classNames[i] == 'user'){
pos = i;
break;
}
}
classNames.splice(i,1);
div.className = classNames.join(' ');
classList,IE10+,chrome,firefox
div[0].classList.remove('username')
div[0].classList.add('current')
div[0].classList.toggle('divClass')
if(div[0].classList.contains('password') && div[0].classList.contains('disabled')){
alert(true)
}
焦点管理
var btn = document.getElementById('myButton')
btn.focus()
alert(document.activeElement == btn) //true
//文档加载完成时,document.activeElement保存的是document.body引用
//确定文档是否获得了焦点
alert(document.hasFocus()) //true
HTMLDocument的变化
1、readyState 两个值 loading:正在加载;complete:已经完成
if(document.readyState == 'complete'){
}
2、document.compatMode 的
值等于"CSS1Compat",而在混杂模式下,document.compatMode 的值等于"BackCompat"。
if (document.compatMode == "CSS1Compat") {
alert("Standards mode");
} else {
alert("Quirks mode");
}
3、head属性
Chrome 和Safari 5。
var head = document.head || document.getElementsByTagName("head")[0];
字符集属性
alert(document.charset); //"UTF-16"
document.charset = "UTF-8";
defaultCharset,表示根据默认浏览器及操作系统的设置,当前文档默认的字符集
应该是什么
if (document.charset != document.defaultCharset){
alert("Custom character set being used.");
}
自定义数据属性
data-,通过dataset访问 ,dataset是DOMStringMap的一个实例,每个data-name形式的属性都会有一个对应的属性,
比如,自定义属性是data-myname,
那映射中对应的属性就是myname)
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
var div = document.getElementById('myDiv')
//获取
var appId = div.dataset.appId;
var myName = div.dataset.myname;
//设置
div.dataset.appId = 123456
div.dataset.myname = 'elmok'
if(div.dataset.myname){
alert('hello ' + div.dataset.myname)
}
插入标记
innerHTML不同浏览器返回的值大小写可能不同
outerHTML返回包括外层
insertAdjacentHTML()两个参数
"beforebegin",在当前元素之前插入一个紧邻的同辈元素;
"afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
"beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
"afterend",在当前元素之后插入一个紧邻的同辈元素。
<div id="content"></div>
//作为前一个同辈元素插入
con.insertAdjacentHTML("beforebegin", "<p>beforebegin!</p>");
//作为第一个子元素插入
con.insertAdjacentHTML("afterbegin", "<p>afterbegin!</p>");
//作为最后一个子元素插入
con.insertAdjacentHTML("beforeend", "<p>beforeend!</p>");
//作为后一个同辈元素插入
con.insertAdjacentHTML("afterend", "<p>afterend!</p>");
之后
<p>beforebegin!</p>
<div id="content">
<p>afterbegin!</p>
<p>beforeend!</p>
</div>
<p>afterend!</p>
在使用innerHTML、
outerHTML 属性和insertAdjacentHTML()方法时,最好先手工删除要被替换的元素的所有事件处理
程序和JavaScript 对象属性
for (var i=0, len=values.length; i < len; i++){
ul.innerHTML += "<li>" + values[i] + "</li>"; //要避免这种频繁操作!!
}
//正确做法
var itemsHtml = "";
...
scrollIntoView(),滚动标准作法
如果给这个方法传入true 作为参数,或者不传入任何参数,那么窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐;
如果传入false 作为参数,调用元素会尽可能全部
出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐。)不过顶部不一定平齐
只有调用才会出现在视口中,类似于a标签本页定位的效果
var btn = document.getElementById('btn')
var div = document.getElementById('content')
btn.onclick = function(){
div.scrollIntoView(true)
}
IE “文档模式”(document mode) 文档模式决定了你可以使用哪个级别的 CSS
要强制浏览器以某种模式渲染页面,可以使用 HTTP头部信息 X-UA-Compatible,或通过等价的 <meta>标签来设置:
//<meta http-equiv="X-UA-Compatible" content="IE=IEVersion">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
var mode = document.documentMode;
alert(mode) // 11/10/9/8/7/5....
children属性
。IE8及更早版本的 children 属性中也会包含注释节点,但 IE9之后的版本则 只返回元素节点
contains()方法.
经常需要知道某个节点是不是另一个节点的后代
alert(document.documentElement.contains(document.body)); //true
- innerText 属性
outerText 属性 //包括父级也替换
滚动
scrollIntoView()
scrollIntoViewIfNeeded(alignCenter):只在当前元素在视口中不可见的情况下,才滚
动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。
如果将可选的alignCenter 参数设置为true,则表示尽量将元素显示在视口中部(垂直方向)。
Safari 和Chrome 实现了这个方法。
scrollByLines(lineCount):将元素的内容滚动指定的行高,lineCount 值可以是正值,
也可以是负值。Safari 和Chrome 实现了这个方法。
scrollByPages(pageCount):将元素的内容滚动指定的页面高度,具体高度由元素的高度决
定。Safari 和Chrome 实现了这个方法。
希望大家要注意的是,scrollIntoView()和scrollIntoViewIfNeeded()的作用对象是元素的
容器,而scrollByLines()和scrollByPages()影响的则是元素自身。下面还是来看几个示例吧。
//将页面主体滚动5 行
document.body.scrollByLines(5);
//在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();
//将页面主体往回滚动1 页
document.body.scrollByPages(-1);
由于scrollIntoView()是唯一一个所有浏览器都支持的方法,因此还是这个方法最常用。