概述
元素与变量名
id属性
由于历史原因,HTML元素的id属性的名字,会自动成为全局变量,指向该HTML元素。
// HTML元素为
// <div id="example"></div>
example // [object HTMLDivElement]
上面代码中,有一个id属性等于example的div元素,结果就自动生成了全局变量example,指向这个div元素。
如果已有同名全局变量,则id元素不会自动生成全局变量。
<script>
var example = 1;
</script>
<div id="example"></div>
<script>
console.log(example) // 1
</script>
上面代码中,已有全局变量example,这时id属性就不会自动变成全局变量。另一情况是,DOM生成以后,再对全局变量example赋值,这时也会覆盖example原来的值。
由于这种原因,默认的全局变量名(比如,history、location、navigator等),最好不要设为id属性的名字。
另外,由于原则上,网页之中不应该有同名id属性的HTML元素,所以,这种机制产生的全局变量不会重名。
name属性
由于历史原因,以下HTML元素的name属性,也会成为全局变量。
<applet><area><embed><form><frame><frameset><iframe><img><object>
// HTML代码为
// <form name="myForm" />
myForm // [object HTMLFormElement]
上面代码中,form元素的name属性名myForm,自动成为全局变量myForm。
如果name属性同名的HTML元素不止一个,或者某个元素的id属性与另一个元素的name属性同名,这时全局变量会指向一个类似数组的对象。
// HTML代码为
// <div id="myForm" />
// <form name="myForm" />
myForm[0] // [object HTMLDivElement]
myForm[1] // [object HTMLFormElement]
上面代码中,全局变量myForm的第一个成员指向div元素,第二个成员指向form元素。
这些元素的name属性名,也会成为document对象的属性。
// HTML代码为<img name="xx" />
document.xx === xx // true
上面代码中,name属性为xx的img元素,自动生成了全局变量xx和document对象的属性xx。
如果有多个name属性相同的元素,那么document对象的该属性指向一个类似数组的对象(NodeList对象的实例)。
这样设计的原意是,通过引用document.elementName就可以获得该元素。但是,由于这些属性是自动生成的,既不规范,也不利于除错,所以建议不要使用它们。
另外,如果iframe元素有name属性或id属性,那么生成的全局变量,不是指向iframe元素节点,而是指向这个iframe代表的子页面window对象。
除了自动成为window和document的属性,带有id或name属性的HTML元素,还会自动成为集合对象的属性。举例来说,如果有一个表单元素<form>。
<form name="myform">
它会自动成为集合对象document.forms的属性。
document.forms.myforms;
Form 元素(表单)
表单主要用于收集用户的输入,送到服务器或者在前端处理。
选中表单元素
如果<form>元素带有name或者id属性,这个元素节点会自动成为window和document的属性,并且可以从document.forms上取到。<form name="myForm">节点用下面几种方法可以拿到。
window.myForm
document.myForm
document.forms.myForm
document.forms[n]
document.forms返回一个类似数组的对象(HTMLCollection的实例),包含了当前页面中所有表单(<form>元素)。HTMLCollection的实例都可以使用某个节点的id和name属性,取到该节点。
表单对象本身也是一个HTMLCollection对象的实例,它里面的各个子节点也可以用id属性、name属性或者索引值取到。举例来说,myForm表单的第一个子节点是<input type="text" name="address">,它可以用下面的方法取到。
document.forms.myForm[0]
document.forms.myForm.address
document.myForm.address
表单节点都有一个elements属性,包含了当前表单的所有子元素,所以也可以用下面的方法取到address子节点。
document.forms.myForm.elements[0]
document.forms.myForm.elements.address
表单之中,会有多个元素共用同一个name属性的情况。
<form name="myForm">
<label><input type="radio" name="method" value="1">1</label>
<label><input type="radio" name="method" value="2">2</label>
<label><input type="radio" name="method" value="3">3</label>
</form>
上面代码中,三个单选框元素共用同一个name属性,这时如果使用这个name属性去引用子节点,返回的将是一个类似数组的对象。
document.forms.myForm.elements.method.length // 3
如果想知道,用户到底选中了哪一个子节点,就必须遍历所有的同名节点。
var methods = document.forms.myForm.elements.method;
var result;
for (var i = 0; i < methods.length; i++) {
if (methods[i].checked) value = methods[i].value;
}
Form 对象
<form>元素对应的DOM节点是一个Form对象。这个对象除了上一小节提到的elements属性,还有以下属性,分别对应元素标签中的同名属性。
actionencodingmethodtarget
Form对象还有两个属性,可以指定事件的回调函数。
onsubmit:提交表单前调用,只要返回false,就会取消提交。可以在这个函数里面,校验用户的输入。该函数只会在用户提交表单时调用,脚本调用submit()方法是不会触发这个函数的。onreset:重置表单前调用,只要返回false,就会取消表单重置。该函数只能由真实的reset按钮触发,脚本调用reset()方法并不会触发这个函数。
<form onreset="return confirm('你要重置表单吗?')">
<!-- ... -->
<button type="reset">重置</button>
</form>
Form对象的方法主要是下面两个。
submit():将表单数据提交到服务器reset():重置表单数据
表单控件对象
表单包含了各种控件,每个控件都是一个对象。它们都包含了以下四个属性。
type:表示控件的类型,对于<input>元素、<button>元素等于这些标签的type属性,对于其他控件,<select>为select-one,<select multiple>为select-multiple,<textarea>为textarea。该属性只读。form:指向包含该控件的表单对象,如果该控件不包含在表单之中,则返回null。该属性只读。name:返回控件标签的name属性。该属性只读。value:返回或设置该控件的值,这个值会被表单提交到服务器。该属性可读写。 才会form属性有一个特别的应用,就是在控件的事件回调函数里面,this指向事件所在的控件对象,所以this.form就指向控件所在的表单,this.form.x就指向其他控件元素,里面的x就是该控件的name属性或id属性的值。
表单控件之中,只要是按钮,都有onclick属性,用来指定用户点击按钮时的回调函数;其他的控件一般都有onchange属性,控件值发生变化,并且该控件失去焦点时调用。单选框(Radio控件)和多选框(Checkbox控件)可以同时设置onchange和onclick属性。
表单控件还有以下两个事件。
focus:得到焦点时触发blur:失去焦点时触发
Select元素
<select>元素用来生成下拉列表。默认情况下,浏览器只显示一条选项,其他选项需要点击下拉按钮才会显示。size选项如果大于1,那么浏览器就会默认显示多个选项。
<select size="3">
上面代码指定默认显示三个选项,更多的选项需要点击下拉按钮才会显示。
<select>元素默认只能选中一个选项,如果想选中多个选项,必须指定multiple属性。
<select multiple>
用户选中或者取消一个下拉选项时,会触发Select对象的change事件,从而自动执行onchange监听函数。
<select>元素有一个options属性,返回一个类似数组的对象,包含了所有的<option>元素。
// HTML 代码为
// <select id="example">
// <option>1</option>
// <option>2</option>
// <option>3</option>
// </select>
var element = document.querySelector('#example');
element.options.length
// 3
上面代码中,<select>元素的options属性包含了三个<option>元素。
options属性可读写,可以通过设置options.length,控制向用户显示的下拉选项的值。将options.length设为0,可以不再显示任何下拉属性。将options里面某个位置的Option对象设为null,将等于移除这个选项,后面的Option对象会自动递补这个位置。
Select对象的selectedIndex属性,返回用户选中的第一个下拉选项的位置(从0开始)。如果返回-1,则表示用户没有选中任何选项。该属性可读写。对于单选的下拉列表,这个属性就可以得知用户的选择;对于多选的下拉列表,这个属性还不够,必须逐个轮询options属性,判断每个Option对象的selected属性是否为true。
Option元素
<option>元素用于在下拉列表(<select>)中生成下拉选项。每个下拉选项就是一个Option对象,它有以下属性。
selected:返回一个布尔值,表示用户是否选中该选项。text:返回该下拉选项的显示的文本。该属性可读写,可用来显示向用户显示的文本。value:返回该下拉选项的值,即向服务器发送的那个值。该属性可读写。defaultSelected:返回一个布尔值,表示这个下拉选项是否默认选中。
浏览器提供Option构造函数,用来生成下拉列表的选项对象。利用这个函数,可以用脚本生成下拉选项,然后放入Select.options对象里面,从而自动生成下拉列表。
var item = new Option(
'Hello World', // 显示的文本,即 text 属性
'myValue', // 向服务器发送的值,即 value 属性
false, // 是否为默认选项,即 defaultSelected 属性
false // 是否已经选中,即 selected 属性
);
// 获取 Selector 对象
var mySelector = document.forms.myForm.mySelector;
mySelector.options[mySelector.options.length] = item;
上面代码在下拉列表的末尾添加了一个选项。从中可以看到,Option构造函数可以接受四个选项,对应<Option>对象的四个属性。
注意,用脚本插入下拉选项完全可以用标准的DOM操作方法实现,比如Document.create Element()、Node.insertBefore()和Node.removeChild()等等。
image元素
alt属性,src属性
alt属性返回image元素的HTML标签的alt属性值,src属性返回image元素的HTML标签的src属性值。
// 方法一:HTML5构造函数Image
var img1 = new Image();
img1.src = 'image1.png';
img1.alt = 'alt';
document.body.appendChild(img1);
// 方法二:DOM HTMLImageElement
var img2 = document.createElement('img');
img2.src = 'image2.jpg';
img2.alt = 'alt text';
document.body.appendChild(img2);
document.images[0].src
// image1.png
complete属性
complete属性返回一个布尔值,true表示当前图像属于浏览器支持的图形类型,并且加载完成,解码过程没有出错,否则就返回false。
height属性,width属性
这两个属性返回image元素被浏览器渲染后的高度和宽度。
naturalWidth属性,naturalHeight属性
这两个属性只读,表示image对象真实的宽度和高度。
myImage.addEventListener('onload', function() {
console.log('My width is: ', this.naturalWidth);
console.log('My height is: ', this.naturalHeight);
});
table元素
表格有一些特殊的DOM操作方法。
- insertRow():在指定位置插入一个新行(tr)。
- deleteRow():在指定位置删除一行(tr)。
- insertCell():在指定位置插入一个单元格(td)。
- deleteCell():在指定位置删除一个单元格(td)。
- createCaption():插入标题。
- deleteCaption():删除标题。
- createTHead():插入表头。
- deleteTHead():删除表头。
下面是使用JavaScript生成表格的一个例子。
var table = document.createElement('table');
var tbody = document.createElement('tbody');
table.appendChild(tbody);
for (var i = 0; i <= 9; i++) {
var rowcount = i + 1;
tbody.insertRow(i);
tbody.rows[i].insertCell(0);
tbody.rows[i].insertCell(1);
tbody.rows[i].insertCell(2);
tbody.rows[i].cells[0].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 1'));
tbody.rows[i].cells[1].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 2'));
tbody.rows[i].cells[2].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 3'));
}
table.createCaption();
table.caption.appendChild(document.createTextNode('A DOM-Generated Table'));
document.body.appendChild(table);
这些代码相当易读,其中需要注意的就是insertRow和insertCell方法,接受一个表示位置的参数(从0开始的整数)。
table元素有以下属性:
- caption:标题。
- tHead:表头。
- tFoot:表尾。
- rows:行元素对象,该属性只读。
- rows.cells:每一行的单元格对象,该属性只读。
- tBodies:表体,该属性只读。
audio元素,video元素
audio元素和video元素加载音频和视频时,以下事件按次序发生。
- loadstart:开始加载音频和视频。
- durationchange:音频和视频的duration属性(时长)发生变化时触发,即已经知道媒体文件的长度。如果没有指定音频和视频文件,duration属性等于NaN。如果播放流媒体文件,没有明确的结束时间,duration属性等于Inf(Infinity)。
- loadedmetadata:媒体文件的元数据加载完毕时触发,元数据包括duration(时长)、dimensions(大小,视频独有)和文字轨。
- loadeddata:媒体文件的第一帧加载完毕时触发,此时整个文件还没有加载完。
- progress:浏览器正在下载媒体文件,周期性触发。下载信息保存在元素的buffered属性中。
- canplay:浏览器准备好播放,即使只有几帧,readyState属性变为CAN_PLAY。
- canplaythrough:浏览器认为可以不缓冲(buffering)播放时触发,即当前下载速度保持不低于播放速度,readyState属性变为CAN_PLAY_THROUGH。
除了上面这些事件,audio元素和video元素还支持以下事件。
| 事件 | 触发条件 |
|---|---|
| abort | 播放中断 |
| emptied | 媒体文件加载后又被清空,比如加载后又调用load方法重新加载。 |
| ended | 播放结束 |
| error | 发生错误。该元素的error属性包含更多信息。 |
| pause | 播放暂停 |
| play | 暂停后重新开始播放 |
| playing | 开始播放,包括第一次播放、暂停后播放、结束后重新播放。 |
| ratechange | 播放速率改变 |
| seeked | 搜索操作结束 |
| seeking | 搜索操作开始 |
| stalled | 浏览器开始尝试读取媒体文件,但是没有如预期那样获取数据 |
| suspend | 加载文件停止,有可能是播放结束,也有可能是其他原因的暂停 |
| timeupdate | 网页元素的currentTime属性改变时触发。 |
| volumechange | 音量改变时触发(包括静音)。 |
| waiting | 由于另一个操作(比如搜索)还没有结束,导致当前操作(比如播放)不得不等待。 |
tabindex属性
tabindex属性用来指定,当前HTML元素节点是否被tab键遍历,以及遍历的优先级。
var b1 = document.getElementById("button1");
b1.tabIndex = 1;
如果tabindex = -1,tab键跳过当前元素。
如果tabindex = 0,表示tab键将遍历当前元素。如果一个元素没有设置tabindex,默认值就是0。
如果tabindex > 0,表示tab键优先遍历。值越大,就表示优先级越大。