元素操作
元素操作
# Attributes(属性)
// 设置变量值
element.style.setProperty("--my-color", "rebeccapurple");
// 获取变量值
element.style.getPropertyValue("--my-color");
// => 'rebeccapurple'
// 移除变量值
element.style.removeProperty("--my-color");
属性判断与获取
以下方法与元素节点的属性相关。
(1)hasAttribute()
hasAttribute
方法返回一个布尔值,表示当前元素节点是否包含指定的 HTML 属性。
const d = document.getElementById("div1");
if (d.hasAttribute("align")) {
d.setAttribute("align", "center");
}
上面代码检查div
节点是否含有align
属性。如果有,则设置为“居中对齐”。
(2)getAttribute()
getAttribute
方法返回当前元素节点的指定属性。如果指定属性不存在,则返回null
。
var div = document.getElementById('div1');
div.getAttribute('align') // "left"
(3)removeAttribute()
removeAttribute 方法用于从当前元素节点移除属性。
// 原来的HTML代码
// <div id="div1" align="left" width="200px">
document.getElementById("div1").removeAttribute("align");
// 现在的HTML代码
// <div id="div1" width="200px">
(4)setAttribute()
setAttribute
方法用于为当前元素节点新增属性,或编辑已存在的属性。
var d = document.getElementById('d1');
d.setAttribute('align', 'center');
该方法会将所有属性名,都当作小写处理。对于那些已存在的属性,该方法是编辑操作,否则就会新建属性。下面是一个对img
元素的src
属性赋值的例子。
var myImage = document.querySelector('img');
myImage.setAttribute ('src', 'path/to/example.png');
大多数情况下,直接对属性赋值比使用该方法更好。
el.value = 'hello';
// or
el.setAttribute('value', 'hello');
而如果是针对于没有值的属性,那么直接填入一个空字符串即可,譬如:
var body = document.getElementsByTagName('body')[0];
body.setAttribute("data-body","");
2
1var body = document.getElementsByTagName('body')[0];
2body.setAttribute("data-body","");
最后达到的效果是:
<body data-body>
1<body data-body>
## 基本属性
(1) attributes
attributes 属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点,每个数字索引对应一个属性节点(Attribute)对象。返回值中,所有成员都是动态的,即属性的变化会实时反映在结果集。下面是一个 HTML 代码:
<p id="para">Hello World</p>
获取 attributes 成员的代码如下。
var para = document.getElementById("para");
var attr = para.attributes[0];
attr.name; // id
attr.value; // para
上面代码说明,通过 attributes 属性获取属性节点对象(attr)以后,可以通过 name 属性获取属性名(id),通过 value 属性获取属性值(para)。注意,属性节点的 name 属性和 value 属性,等同于 nodeName 属性和 nodeValue 属性。如果需要遍历一个节点的所有属性,可以用如下方式:
var para = document.getElementsByTagName("p")[0];
if (para.hasAttributes()) {
var attrs = para.attributes;
var output = "";
for (var i = attrs.length - 1; i >= 0; i--) {
output += attrs[i].name + "->" + attrs[i].value;
}
result.value = output;
} else {
result.value = "No attributes to show";
}
(2) id 属性
id 属性返回指定元素的 id 标识。该属性可读写。
(3) tagName 属性
tagName 属性返回指定元素的大写的标签名,与 nodeName 属性的值相等。
// 假定HTML代码如下 //
<span id="span">Hello</span> var span = document.getElementById("span");
span.tagName // "SPAN"
## 文本与值属性
### innerHTML & outerHTML
innerHTML 属性返回该元素包含的 HTML 代码。该属性可读写,常用来设置某个节点的内容。如果将该属性设为空,等于删除所有它包含的所有节点。
el.innerHTML = "";
上面代码等于将 el 节点变成了一个空节点,el 原来包含的节点被全部删除。注意,如果文本节点中包含&、小于号(<)和大于号(%gt;),innerHTML 属性会将它们转为实体形式&、<、>。
// HTML代码如下 <p id="para"> 5 > 3 </p>
document.getElementById("para").innerHTML;
// 5 > 3
由于上面这个原因,导致在 innerHTML 插入 <script>
标签,不会被执行。
var name = "<script>alert('haha')</script>";
el.innerHTML = name;
上面代码将脚本插入内容,脚本并不会执行。但是,innerHTML 还是有安全风险的。
var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;
上面代码中,alert 方法是会执行的。因此为了安全考虑,如果插入的是文本,最好用 textContent 属性代替 innerHTML。并且在不同的浏览器,特别是 IE 浏览器中表现差异很大。在 IE 中,innerHTML 对于 COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR 是只读的。在 IE 中, innerHTML 对于所有的表格相关标签都是只读的(除了 TD 标签)。另外,innerHTML
不能被追加。通常情况下, 我们可以通过 innerHTML 追加内容(elem.innerHTML += “NEW TEXT”), 例如:
chatDiv.innerHTML += "<div>Hi <img src='smile.gif'/> !</div>"
chatDiv.innerHTML += "How you doing?"
但是实际他是这样工作的:
- 原来的内容被去除
- 新的值通过 innerHTML 解析替换. 内容不能被追加, 他是重新构建的. 因此, 所有的图片和其他资源在+=之后, 将会被重载. 比如上面的例子的 smile.gif 文件。 ## 样式属性
className 属性用来读取和设置当前元素的 class 属性。它的值是一个字符串,每个 class 之间用空格分割。
classList 属性则返回一个类似数组的对象,当前元素节点的每个 class 就是这个对象的一个成员。
<div class="one two three" id="myDiv"></div>
上面这个 div 元素的节点对象的 className 属性和 classList 属性,分别如下。
document.getElementById('myDiv').className
// "one two three"
document.getElementById('myDiv').class List
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }
从上面代码可以看出,className 属性返回一个空格分隔的字符串,而 classList 属性指向一个类似数组的对象,该对象的 length 属性(只读)返回当前元素的 class 数量。
classList 对象有下列方法。
- add():增加一个 class。 - remove():移除一个 class。 - contains():检查当前元素是否包含某个 class。 - toggle():将某个 class 移入或移出当前元素。 - item():返回指定索引位置的 class。 - toString():将 class 的列表转为字符串。
myDiv.classList.add('myCssClass');
myDiv.classList.add('foo', 'bar');
myDiv.classList.remove('myCssClass');
myDiv.classList.toggle('myCssClass'); // 如果myCssClass不存在就加入,否则移除
myDiv.classList.contains('myCssClass'); // 返回 true 或者 false
myDiv.classList.item(0); // 返回第一个Class
myDiv.classList.toString();
下面比较一下,className 和 classList 在添加和删除某个类时的写法。
// 添加class
document.getElementById('foo').className += 'bold';
document.getElementById('foo').classList.add('bold');
// 删除class
document.getElementById('foo').classList.remove('bold');
document.getElementById('foo').className =
document.getElementById('foo').className.replace(/^bold$/, '');
toggle 方法可以接受一个布尔值,作为第二个参数。如果为 true,则添加该属性;如果为 false,则去除该属性。
el.classList.toggleClass("abc", someBool);
// 等同于
if (someBool){
el.classList.add("abc");
} else {
el.classList.remove("abc");
}
document.getElementById("myH1").style.color = "red";
## 尺寸属性
以下属性与元素节点的可见区域的坐标相关。
(1)clientHeight
clientHeight 属性返回元素节点的可见高度,包括 padding、但不包括水平滚动条、边框和 margin 的高度,单位为像素。该属性可以计算得到,等于元素的 CSS 高度,加上 CSS 的 padding 高度,减去水平滚动条的高度(如果存在水平滚动条)。
如果一个元素是可以滚动的,则 clientHeight 只计算它的可见部分的高度。
(2)clientLeft
clientLeft 属性等于元素节点左边框(border)的宽度,单位为像素,包括垂直滚动条的宽度,不包括左侧的 margin 和 padding。但是,除非排版方向是从右到左,且发生元素宽度溢出,否则是不可能存在左侧滚动条。如果该元素的显示设为display: inline
,clientLeft 一律为 0,不管是否存在左边框。
(3)clientTop
clientTop 属性等于网页元素顶部边框的宽度,不包括顶部的 margin 和 padding。
(4)clientWidth
clientWidth 属性等于网页元素的可见宽度,即包括 padding、但不包括垂直滚动条(如果有的话)、边框和 margin 的宽度,单位为像素。
如果一个元素是可以滚动的,则 clientWidth 只计算它的可见部分的宽度。
## 位移与状态属性
以下属性与元素节点占据的总区域的坐标相关。
(1)scrollHeight
scrollHeight 属性返回指定元素的总高度,包括由于溢出而无法展示在网页的不可见部分。如果一个元素是可以滚动的,则 scrollHeight 包括整个元素的高度,不管是否存在垂直滚动条。scrollHeight 属性包括 padding,但不包括 border 和 margin。该属性为只读属性。
如果不存在垂直滚动条,scrollHeight 属性与 clientHeight 属性是相等的。如果存在滚动条,scrollHeight 属性总是大于 clientHeight 属性。当滚动条滚动到内容底部时,下面的表达式为 true。
element.scrollHeight - element.scrollTop === element.clientHeight
如果滚动条没有滚动到内容底部,上面的表达式为 false。这个特性结合onscroll
事件,可以判断用户是否滚动到了指定元素的底部,比如是否滚动到了《使用须知》区块的底部。
var rules = document.getElementById("rules");
rules.onscroll = checking;
function checking(){
if (this.scrollHeight - this.scrollTop === this.clientHeight) {
console.log('谢谢阅读');
} else {
console.log('您还未读完');
}
}
(2)scrollWidth
scrollWidth 属性返回元素的总宽度,包括由于溢出容器而无法显示在网页上的那部分宽度,不管是否存在水平滚动条。该属性是只读属性。
(3)scrollLeft
scrollLeft 属性设置或返回水平滚动条向右侧滚动的像素数量。它的值等于元素的最左边与其可见的最左侧之间的距离。对于那些没有滚动条或不需要滚动的元素,该属性等于 0。该属性是可读写属性,设置该属性的值,会导致浏览器将指定元素自动滚动到相应的位置。
(4)scrollTop
scrollTop 属性设置或返回垂直滚动条向下滚动的像素数量。它的值等于元素的顶部与其可见的最高位置之间的距离。对于那些没有滚动条或不需要滚动的元素,该属性等于 0。该属性是可读写属性,设置该属性的值,会导致浏览器将指定元素自动滚动到相应位置。
document.querySelector('div').scrollTop = 150;
上面代码将 div 元素向下滚动 150 像素。
Operation(元素操作)
## 创建与插入
创建一个新的 DOM 节点主要依赖于一下几个方法:
createDocumentFragment(); //创建一个DOM片段
createElement(); //创建一个具体的元素
createTextNode(); //创建一个文本节点
对于如下这个 HTML 片段:
<ul id="myList">
<li>项目一</li>
<li>项目二</li>
<li>项目三</li>
</ul>
首先需要依靠document.createElement()
方法来创建元素,接受一个参数,即要创建元素的标签名,返回创建的元素节点。
var div = document.createElement("div"); //创建一个div元素
div.id = "myDiv"; //设置div的id
div.className = "box"; //设置div的class
在创建元素后,还需要把元素添加到文档树中,主要依靠 appendChild 方法:
var ul = document.getElementById("myList"); //获得ul
var li = document.createElement("li"); //创建li
li.innerHTML = "项目四"; //向li内添加文本
ul.appendChild(li); //把li 添加到ul子节点的末尾
添加之后变成了:
<ul id="myList">
<li>项目一</li>
<li>项目二</li>
<li>项目三</li>
<li>项目四</li>
</ul>
appendChild() 方法还可以添加已经存在的元素,会将元素从原来的位置移到新的位置
var ul = document.getElementById("myList"); //获得ul
ul.appendChild(ul.firstChild); //把ul的第一个元素节点移到ul子节点的末尾
运行后(IE):
<ul id="myList">
<li>项目二</li>
<li>项目三</li>
<li>项目一</li>
</ul>
insertBefore() 方法,如果不是在末尾插入节点,而是想放在特定的位置上,用这个方法,该方法接受 2 个参数,第一个是要插入的节点,第二个是参照节点,返回要添加的元素节点
var ul = document.getElementById("myList"); //获得ul
var li = document.createElement("li"); //创建li
li.innerHTML= "项目四"; //向li内添加文本
ul.insertBefore(li,ul.firstChild); //把li添加到ul的第一个子节点前
添加后:
<ul id="myList">
<li>项目四</li>
<li>项目一</li>
<li>项目二</li>
<li>项目三</li>
</ul>
var ul = document.getElementById("myList"); //获得ul
var li = document.createElement("li"); //创建li
li.innerHTML = "项目四"; //向li内添加文本
ul.insertBefore(li, ul.lastChild); //把li添加到ul的子节点末尾
添加后:
<ul id="myList">
<li>项目一</li>
<li>项目二</li>
<li>项目三</li>
<li>项目四</li>
</ul>
<script>
var ul = document.getElementById("myList"); //获得ul
var li = document.createElement("li"); //创建li
li.innerHTML = "项目四"; //向li内添加文本
var lis = ul.getElementsByTagName("li"); //获取ul中所有li的集合
ul.insertBefore(li, lis[1]); //把li添加到ul中的第二个li节点前
</script>
添加后:
<ul id="myList">
<li>项目一</li>
<li>项目四</li>
<li>项目二</li>
<li>项目三</li>
</ul>
## 移除与替换
移除元素节点
removeChild() 方法 ,用于移除节点,接受一个参数,即要移除的节点,返回被移除的节点,注意被移除的节点仍然在文档中,不过文档中已没有其位置了
var ul = document.getElementById("myList"); //获得ul
var fromFirstChild = ul.removeChild(ul.firstChild); //移除ul第一个子节点
var ul = document.getElementById("myList"); //获得ul
var lis = ul.getElementsByTagName("li") //获取ul中所有li的集合
ul.removeChild(lis[0]); //移除第一个li,与上面不同,要考虑浏览器之间的差异
替换元素节点
replaceChild() 方法 ,用于替换节点,接受两个参数,第一参数是要插入的节点,第二个是要替换的节点,返回被替换的节点
var ul = document.getElementById("myList"); //获得ul
var fromFirstChild = ul.replaceChild(ul.firstChild); //替换ul第一个子节点
var ul = document.getElementById("myList"); //获得ul;
var li = document.createElement("li"); //创建li
li.innerHTML= "项目四"; //向li内添加文本
var lis = ul.getElementsByTagName("li") //获取ul中所有li的集合
var returnNode = ul.replaceChild(li,lis[1]); //用创建的li替换原来的第二个li
复制节点
cloneNode() 方法,用于复制节点, 接受一个布尔值参数, true 表示深复制(复制节点及其所有子节点), false 表示浅复制(复制节点本身,不复制子节点)
var ul = document.getElementById("myList"); //获得ul
var deepList = ul.cloneNode(true); //深复制
var shallowList = ul.cloneNode(false); //浅复制
# Document
元素样式
// Add Rules to Stylesheets with JavaScript
// http://davidwalsh.name/add-rules-stylesheets
/* Getting the Stylesheet
Which stylesheet you add the rules to is up to you. If you have a specific stylesheet in mind, you can add an ID to the LINK or STYLE element within your page HTML and get the CSSStyleSheet object by referencing the element's sheet property. The stylesheets can be found in the document.styleSheets object:*/
var sheets = document.styleSheets; // returns an Array-like StyleSheet List
/*
Returns:
StyleSheetList {0: CSSStyleSheet, 1: CSSStyleSheet, 2: CSSStyleSheet, 3: CSSStyleSheet, 4: CSSStyleSheet, 5: CSSStyleSheet, 6: CSSStyleSheet, 7: CSSStyleSheet, 8: CSSStyleSheet, 9: CSSStyleSheet, 10: CSSStyleSheet, 11: CSSStyleSheet, 12: CSSStyleSheet, 13: CSSStyleSheet, 14: CSSStyleSheet, 15: CSSStyleSheet, length: 16, item: function}
*/
// Grab the first sheet, regardless of media
var sheet = document.styleSheets[0];
/* Creating a New Stylesheet
In many cases, it may just be best to create a new STYLE element for your dynamic rules. This is quite easy:*/
var sheet = (function () {
// Create the <style> tag
var style = document.createElement("style");
// Add a media (and/or media query) here if you'd like!
// style.setAttribute("media", "screen")
// style.setAttribute("media", "@media only screen and (max-width : 1024px)")
// WebKit hack :(
style.appendChild(document.createTextNode(""));
// Add the <style> element to the page
document.head.appendChild(style);
return style.sheet;
})();
/* Adding Rules
CSSStyleSheet objects have an addRule method which allows you to register CSS rules within the stylesheet. The addRule method accepts three arguments: the selector, the second the CSS code for the rule, and the third is the zero-based integer index representing the style position (in relation to styles of the same selector): */
sheet.addRule("#myList li", "float: left; background: red !important;", 1);
/* Inserting Rules
Stylesheets also have an insertRule method which isn't available in earlier IE's. The insertRule combines the first two arguments of addRule: */
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);
/* Safely Applying Rules
Since browser support for insertRule isn't as global, it's best to create a wrapping function to do the rule application. Here's a quick and dirty method: */
function addCSSRule(sheet, selector, rules, index) {
if (sheet.insertRule) {
sheet.insertRule(selector + "{" + rules + "}", index);
} else {
sheet.addRule(selector, rules, index);
}
}
// Use it!
addCSSRule(document.styleSheets[0], "header", "float: left");
/* Inserting Rules for Media Queries
Media query-specific rules can be added in one of two ways. The first way is through the standard insertRule method: */
sheet.insertRule(
"@media only screen and (max-width : 1140px) { header { display: none; } }"
);