在外部文件中放置脚本有如下优势:
- 分离了 HTML 和代码
- 使 HTML 和 JavaScript 更易于阅读和维护
- 已缓存的 JavaScript 文件可加速页面加载
如需向一张页面添加多个脚本文件 - 请使用多个 script 标签:
JavaScript 能够以不同方式“显示”数据:
- 使用
window.alert()
写入警告框 - 使用
document.write()
写入 HTML 输出 - 使用
innerHTML
写入 HTML 元素 - 使用
console.log()
写入浏览器控制台
innerHTML
如需访问 HTML 元素,JavaScript 可使用 document.getElementById(id)
方法。
id
属性定义 HTML 元素。innerHTML 属性定义 HTML 内容:
<!DOCTYPE html>
<html>
<body><h1>我的第一张网页</h1><p>我的第一个段落</p><p id="demo"></p><script>document.getElementById("demo").innerHTML = 5 + 6;
</script></body>
</html>
使用 document.write()
出于测试目的,使用 document.write()
比较方便:4
<!DOCTYPE html>
<html>
<body><h1>我的第一张网页</h1><p>我的第一个段落</p><script>
document.write(5 + 6);
</script></body>
</html>
使用 window.alert()
您能够使用警告框来显示数据:
<!DOCTYPE html>
<html>
<body><h1>我的第一张网页</h1><p>我的第一个段落</p><script>
window.alert(5 + 6);
</script></body>
</html>
使用 console.log()
在浏览器中,您可使用 console.log()
方法来显示数据。请通过 F12 来激活浏览器控制台,并在菜单中选择“控制台”。
<!DOCTYPE html>
<html>
<body><h1>我的第一张网页</h1><p>我的第一个段落</p><script>
console.log(5 + 6);
</script></body>
</html>
Javascript对象学习
通过创建对应的Object方式创建的对象实例
var person = new Object();person.name = "John";
person.age = 30;
person.job = "banker";
person.sayname = function(){alert(this.name)
}
同样可以通过以下的方式实现对应
var person2 = {name: "John",age: 30,job: "banker",sayname: function(){alert(this.age)}
}
属性的类型,ECMAScript中有两种对应的属性,数据属性和访问器属性
数据属性
[Configurable]:表示是否可以通过对应delete删除属性从而重新定义属性。能否修改属性的特性,或者是否能够把属性的修改的访问器的属性
[Enumerable]:表示能够通过for in 返回属性
[Writeable]:表示能够是否修改属性的值,
[value]:包含这个属性的value,读写数据的时候可以把对应的值放在这个位置
var person2 = {};
Object.defineProperty(person2,"name",{writable: false,value: "John"
})
alert(person2.name);
person2.name = "John1";
alert(person2.name);
发现把对应的name属性设置为只读的,故所以只能进行对应的改
访问器属性
访问器的属性不包含对应的数据值,他们包含一对getter和setter函数(并不是必须的),在读取属性的器的值的,会调用对应getter函数,返回对应的属性值。在设置对应的属性值是,会调用对应的setter并传入新的值。
[Configurable]:表示是否可以通过对应delete删除属性从而重新定义属性。能否修改属性的特性,或者是否能够把属性的修改的访问器的属性
[Enumerable]:表示能够通过for in 返回属性
[get]:在读取属性时调用的函数
[set]:在写入属性的时候调用
var book = {_year: 2004,edition: 1
}
Object.defineProperty( book,"year".{get: function(){return this._year;},set : function(newValue){if( newValue > 2004){this._year = newValue;this.edition+=newValue-2004;}}
}
)book.year = 2005;
alert(book.edition);
创建对应的属性
虽然Object构造函数或者对应的字面标量的都可以用来创建对应的单个对象,这些方式有个明显的缺点,使用同一个的接口创建很多的对象,会产生大量的重复。
工厂模式:
function CreateObject(name,age,job){var o = new Object();o.name = name;o.age = age;o.job = job;o.sayname = function(){alert(this.name);}return o;
}
缺点:没有解决对应的对象识别的问题
构造函数模式
function Person(name, age,job){this.name = name;this.age = age;this.job = job;this.sayname = function(){alert(this.name);}
}
var person = new Person("John", 30, "banker");
var person2 = new Person("John", 30, "software Engineer");
在这个例子中使用,Person代替了CreateObject。但是
- 函数中并没有出现显示的对象创建
- 直接将对应的属性和方法进行赋值
- 没有对应的return
- 对应的构造函首字母需要进行大写进行保持
要使用对应的对象必须使用new进行对应的创建。
// 构造函数标识对象
alert(person.constructor == Person)
alert(person2.constructor == Person)// 当检查是否为对象时可以使用
alert(person instanceof Object)
alert(person2 instanceof Object)
原型模式
// 原型模式
function Person(){}Person.prototype.name = "John"
Person.prototype.age = 30
Person.prototype.job = "banker"
Person.prototype.sayname = function(){alert(this.name)
}var person1 = new Person()
person1.sayname()var person2 = new Person()
person2.sayname()alert(person1.constructor == person2.constructor)
首先,这个构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值,因为 Car1 和 Car2 的 color 属性都等于 "blue",doors 属性都等于 4,mpg 属性都等于 25。这意味着必须在对象创建后才能改变属性的默认值,这点很令人讨厌
混合的构造函数/原型方式
function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");}Car.prototype.showColor = function() {alert(this.color);};var oCar1 = new Car("red",4,23);var oCar2 = new Car("blue",3,25);oCar1.drivers.push("Bill");alert(oCar1.drivers); //输出 "Mike,John,Bill"alert(oCar2.drivers); //输出 "Mike,John"
所有的非函数属性都在构造函数中创建,意味着又能够用构造函数的参数赋予属性默认值了。因为只创建 showColor() 函数的一个实例,所以没有内存浪费。
动态原型方法
function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");if (typeof this.showColor != "function") {Car.prototype.showColor = function() {alert(this.color);};Car._initialized = true;}}
继承
说明继承机制最简单的方式是,利用一个经典的例子 - 几何形状。实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边)。圆是椭圆的一种,它只有一个交点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了一种完美的继承关系。
在这个例子中,形状(Shape)是椭圆形(Ellipse)和多边形(Polygon)的基类(base class)(所有类都由它继承而来)。椭圆具有一个属性 foci,说明椭圆具有的焦点的个数。圆形(Circle)继承了椭圆形,因此圆形是椭圆形的子类(subclass),椭圆形是圆形的超类(superclass)。同样,三角形(Triangle)、矩形(Rectangle)和五边形(Pentagon)都是多边形的子类,多边形是它们的超类。最后,正方形(Square)继承了矩形。
最好用图来解释这种继承关系,这是 UML(统一建模语言)的用武之地。UML 的主要用途之一是,可视化地表示像继承这样的复杂对象关系。下面的图示是解释 Shape 和它的子类之间关系的 UML 图示:
继承机制的实现
要用 ECMAScript 实现继承机制,您可以从要继承的基类入手。所有开发者定义的类都可作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。
选定基类后,就可以创建它的子类了。是否使用基类完全由你决定。有时,你可能想创建一个不能直接使用的基类,它只是用于给子类提供通用的函数。在这种情况下,基类被看作抽象类。
尽管 ECMAScript 并没有像其他语言那样严格地定义抽象类,但有时它的确会创建一些不允许使用的类。通常,我们称这种类为抽象类。
创建的子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。
继承的方式
和其他功能一样,ECMAScript 实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。这意味着所有的继承细节并非完全由解释程序处理。作为开发者,你有权决定最适用的继承方式。
下面为您介绍几种具体的继承方式。
对象冒充
构想原始的 ECMAScript 时,根本没打算设计对象冒充(object masquerading)。它是在开发者开始理解函数的工作方式,尤其是如何在函数环境中使用 this 关键字后才发展出来。
其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使 ClassA 构造函数成为 ClassB 的方法,然后调用它。ClassB 就会收到 ClassA 的构造函数中定义的属性和方法。例如,用下面的方式定义 ClassA 和 ClassB:
function ClassA(sColor) {this.color = sColor;this.sayColor = function () {alert(this.color);};
}function ClassB(sColor) {
}
还记得吗?关键字 this 引用的是构造函数当前创建的对象。不过在这个方法中,this 指向的所属的对象。这个原理是把 ClassA 作为常规函数来建立继承机制,而不是作为构造函数。如下使用构造函数 ClassB 可以实现继承机制:
function ClassB(sColor) {this.newMethod = ClassA;this.newMethod(sColor);delete this.newMethod;
}
在这段代码中,为 ClassA 赋予了方法 newMethod(请记住,函数名只是指向它的指针)。然后调用该方法,传递给它的是 ClassB 构造函数的参数 sColor。最后一行代码删除了对 ClassA 的引用,这样以后就不能再调用它。
所有新属性和新方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法:
function ClassB(sColor, sName) {this.newMethod = ClassA;this.newMethod(sColor);delete this.newMethod;this.name = sName;this.sayName = function () {alert(this.name);};
}
为证明前面的代码有效,可以运行下面的例子:
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor(); //输出 "blue"
objB.sayColor(); //输出 "red"
objB.sayName(); //输出 "John"
对象冒充可以实现多重继承
有趣的是,对象冒充可以支持多重继承。也就是说,一个类可以继承多个超类。用 UML 表示的多重继承机制如下图所示:
function ClassZ() {this.newMethod = ClassX;this.newMethod();delete this.newMethod;this.newMethod = ClassY;this.newMethod();delete this.newMethod;
}
这里存在一个弊端,如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。
由于这种继承方法的流行,ECMAScript 的第三版为 Function 对象加入了两个方法,即 call() 和 apply()。
all() 方法
call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身。
function sayColor(sPrefix,sSuffix) {alert(sPrefix + this.color + sSuffix);
};var obj = new Object();
obj.color = "blue";sayColor.call(obj, "The color is ", "a very nice color indeed.");
在这个例子中,函数 sayColor() 在对象外定义,即使它不属于任何对象,也可以引用关键字 this。对象 obj 的 color 属性等于 blue。调用 call() 方法时,第一个参数是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。第二个和第三个参数是字符串。它们与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,最后生成的消息 "The color is blue, a very nice color indeed." 将被显示出来。
要与继承机制的对象冒充方法一起使用该方法,只需将前三行的赋值、调用和删除代码替换即可
function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.call(this, sColor);this.name = sName;this.sayName = function () {alert(this.name);};
}
apply() 方法
apply() 方法有两个参数,用作 this 的对象和要传递给函数的参数的数组。例如:
function sayColor(sPrefix,sSuffix) {alert(sPrefix + this.color + sSuffix);
};var obj = new Object();
obj.color = "blue";sayColor.apply(obj, new Array("The color is ", "a very nice color indeed."));
这个例子与前面的例子相同,只是现在调用的是 apply() 方法。调用 apply() 方法时,第一个参数仍是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。第二个参数是由两个字符串构成的数组,与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,最后生成的消息仍是 "The color is blue, a very nice color indeed.",将被显示出来。
该方法也用于替换前三行的赋值、调用和删除新方法的代码:
function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.apply(this, new Array(sColor));this.name = sName;this.sayName = function () {alert(this.name);};
}
同样的,第一个参数仍是 this,第二个参数是只有一个值 color 的数组。可以把 ClassB 的整个 arguments 对象作为第二个参数传递给 apply() 方法:
function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.apply(this, arguments);this.name = sName;this.sayName = function () {alert(this.name);};
}
原型链(prototype chaining)
继承这种形式在 ECMAScript 中原本是用于原型链的。上一章介绍了定义类的原型方式。原型链扩展了这种方式,以一种有趣的方式实现继承机制。
function ClassA() {
}ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {alert(this.color);
};function ClassB() {
}ClassB.prototype = new ClassA();
function ClassB() {
}ClassB.prototype = new ClassA();ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {alert(this.name);
};
var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor();
objB.sayColor();
objB.sayName();
此外,在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。例如:
var objB = new ClassB();
alert(objB instanceof ClassA); //输出 "true"
alert(objB instanceof ClassB); //输出 "true"
混合方式
这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。
在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:
function ClassA(sColor) {this.color = sColor;
}ClassA.prototype.sayColor = function () {alert(this.color);
};function ClassB(sColor, sName) {ClassA.call(this, sColor);this.name = sName;
}ClassB.prototype = new ClassA();ClassB.prototype.sayName = function () {alert(this.name);
};
在此例子中,继承机制由两行突出显示的蓝色代码实现。在第一行突出显示的代码中,在 ClassB 构造函数中,用对象冒充继承 ClassA 类的 sColor 属性。在第二行突出显示的代码中,用原型链继承 ClassA 类的方法。由于这种混合方式使用了原型链,所以 instanceof 运算符仍能正确运行。
下面的例子测试了这段代码:
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor(); //输出 "blue"
objB.sayColor(); //输出 "red"
objB.sayName(); //输出 "John"
JavaScript HTML DOM
通过 HTML DOM,JavaScript 能够访问和改变 HTML 文档的所有元素。
HTML DOM(文档对象模型)
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
HTML DOM 模型被结构化为对象树:
通过这个对象模型,JavaScript 获得创建动态 HTML 的所有力量:
- JavaScript 能改变页面中的所有 HTML 元素
- JavaScript 能改变页面中的所有 HTML 属性
- JavaScript 能改变页面中的所有 CSS 样式
- JavaScript 能删除已有的 HTML 元素和属性
- JavaScript 能添加新的 HTML 元素和属性
- JavaScript 能对页面中所有已有的 HTML 事件作出反应
- JavaScript 能在页面中创建新的 HTML 事件
HTML DOM 属性是您能够设置或改变的 HTML 元素的值
HTML DOM 能够通过 JavaScript 进行访问(也可以通过其他编程语言)。
在 DOM 中,所有 HTML 元素都被定义为对象。
编程界面是每个对象的属性和方法。
属性是您能够获取或设置的值(就比如改变 HTML 元素的内容)。
方法是您能够完成的动作(比如添加或删除 HTML 元素)。
<!DOCTYPE html>
<html>
<body><h2>我的第一张网页</h2><p id="demo"></p><script>
document.getElementById("demo").innerHTML = "Hello World!";
</script></body>
</html>
getElementById 方法
访问 HTML 元素最常用的方法是使用元素的 id。
在上面的例子中,getElementById
方法使用 id="demo" 来查找元素。
innerHTML 属性
获取元素内容最简单的方法是使用 innerHTML
属性。
innerHTML
属性可用于获取或替换 HTML 元素的内容。
innerHTML
属性可用于获取或改变任何 HTML 元素,包括 <html>
和 <body>
。
HTML DOM Document 对象
文档对象代表您的网页。如果您希望访问 HTML 页面中的任何元素,那么您总是从访问 document 对象开始。
下面是一些如何使用 document 对象来访问和操作 HTML 的实例。
查找 HTML 元素
方法 | 描述 |
---|---|
document.getElementById(id) | 通过元素 id 来查找元素 |
document.getElementsByTagName(name) | 通过标签名来查找元素 |
document.getElementsByClassName(name) | 通过类名来查找元素 |
改变 HTML 元素
方法 | 描述 |
---|---|
element.innerHTML = new html content | 改变元素的 inner HTML |
element.attribute = new value | 改变 HTML 元素的属性值 |
element.setAttribute(attribute, value) | 改变 HTML 元素的属性值 |
element.style.property = new style | 改变 HTML 元素的样式 |
添加和删除元素
方法 | 描述 |
---|---|
document.createElement(element) | 创建 HTML 元素 |
document.removeChild(element) | 删除 HTML 元素 |
document.appendChild(element) | 添加 HTML 元素 |
document.replaceChild(element) | 替换 HTML 元素 |
document.write(text) | 写入 HTML 输出流 |
添加事件处理程序
方法 | 描述 |
---|---|
document.getElementById(id).onclick = function(){code} | 向 onclick 事件添加事件处理程序 |
查找 HTML 对象
首个 HTML DOM Level 1 (1998),定义了 11 个 HTML 对象、对象集合和属性。它们在 HTML5 中仍然有效。
后来,在 HTML DOM Level 3,加入了更多对象、集合和属性。
属性 | 描述 | DOM |
---|---|---|
document.anchors | 返回拥有 name 属性的所有 <a> 元素。 | 1 |
document.applets | 返回所有 <applet> 元素(HTML5 不建议使用) | 1 |
document.baseURI | 返回文档的绝对基准 URI | 3 |
document.body | 返回 <body> 元素 | 1 |
document.cookie | 返回文档的 cookie | 1 |
document.doctype | 返回文档的 doctype | 3 |
document.documentElement | 返回 <html> 元素 | 3 |
document.documentMode | 返回浏览器使用的模式 | 3 |
document.documentURI | 返回文档的 URI | 3 |
document.domain | 返回文档服务器的域名 | 1 |
document.domConfig | 废弃。返回 DOM 配置 | 3 |
document.embeds | 返回所有 <embed> 元素 | 3 |
document.forms | 返回所有 <form> 元素 | 1 |
document.head | 返回 <head> 元素 | 3 |
document.images | 返回所有 <img> 元素 | 1 |
document.implementation | 返回 DOM 实现 | 3 |
document.inputEncoding | 返回文档的编码(字符集) | 3 |
document.lastModified | 返回文档更新的日期和时间 | 3 |
document.links | 返回拥有 href 属性的所有 <area> 和 <a> 元素 | 1 |
document.readyState | 返回文档的(加载)状态 | 3 |
document.referrer | 返回引用的 URI(链接文档) | 1 |
document.scripts | 返回所有 <script> 元素 | 3 |
document.strictErrorChecking | 返回是否强制执行错误检查 | 3 |
document.title | 返回 <title> 元素 | 1 |
document.URL | 返回文档的完整 URL | 1 |
查找 HTML 元素
通常,通过 JavaScript,您需要操作 HTML 元素。
为了达成此目的,您需要首先找到这些元素。有好几种完成此任务的方法:
- 通过 id 查找 HTML 元素
- 通过标签名查找 HTML 元素
- 通过类名查找 HTML 元素
- 通过 CSS 选择器查找 HTML 元素
- 通过 HTML 对象集合查找 HTML 元素
通过 id 查找 HTML 元素
DOM 中查找 HTML 元素最简单的方法是,使用元素的 id。
本例查找 id="intro" 的元素:
<!DOCTYPE html>
<html>
<body><h1>通过 id 查找 HTML 元素</h1><p id="intro">Hello World!</p><p>本例演示 <b>getElementsById</b> 方法。</p><p id="demo"></p><script>
var myElement = document.getElementById("intro");
document.getElementById("demo").innerHTML =
"来自 intro 段落的文本是:" + myElement.innerHTML;
</script></body>
</html>
通过标签名查找 HTML 元素
本例查找所有 <p>
元素:
<!DOCTYPE html>
<html>
<body><h1>通过标签名查找 HTML 元素</h1><p>Hello World!</p><p>本例演示 <b>getElementsByTagName</b> 方法。</p><p id="demo"></p><script>
var x = document.getElementsByTagName("p");
document.getElementById("demo").innerHTML =
'第一段中的文本 (index 0) 是:' + x[0].innerHTML;
</script></body>
</html>
通过类名查找 HTML 元素
如果您需要找到拥有相同类名的所有 HTML 元素,请使用 getElementsByClassName()
。
本例返回包含 class="intro" 的所有元素的列表:
<!DOCTYPE html>
<html>
<body><h1>通过类名查找 HTML 元素</h1><p>Hello World!</p><p class="intro">DOM 很有用。</p><p class="intro">本例演示 <b>getElementsByClassName</b> 方法。</p><p id="demo"></p><script>
var x = document.getElementsByClassName("intro");
document.getElementById("demo").innerHTML =
'class ="intro" 的第一段(索引 0):' + x[0].innerHTML;
</script></body>
</html>
通过 CSS 选择器查找 HTML 元素
如果您需要查找匹配指定 CSS 选择器(id、类名、类型、属性、属性值等等)的所有 HTML 元素,请使用 querySelectorAll()
方法。
<!DOCTYPE html>
<html>
<body><h1>按查询选择器查找 HTML 元素</h1><p>Hello World!</p><p class="intro">DOM 很有用。</p><p class="intro">本例演示 <b>querySelectorAll</b> 方法。</p><p id="demo"></p><script>
var x = document.querySelectorAll("p.intro");
document.getElementById("demo").innerHTML =
'class ="intro" 的第一段(索引 0):' + x[0].innerHTML;
</script></body>
</html>
通过 HTML 对象选择器查找 HTML 对象
本例查找 id="frm1" 的 form 元素,在 forms 集合中,然后显示所有元素值:
<!DOCTYPE html>
<html>
<body><h1>使用 document.forms 查找 HTML 元素</h1><form id="frm1" action="/demo/demo_form.asp">First name: <input type="text" name="fname" value="Bill"><br>Last name: <input type="text" name="lname" value="Gates"><br><br><input type="submit" value="提交">
</form> <p>单击“试一试”按钮,显示表单中每个元素的值。</p><button onclick="myFunction()">试一试</button><p id="demo"></p><script>
function myFunction() {var x = document.forms["frm1"];var text = "";var i;for (i = 0; i < x.length ;i++) {text += x.elements[i].value + "<br>";}document.getElementById("demo").innerHTML = text;
}
</script></body>
</html>
JavaScript HTML DOM - 改变 HTML
改变 HTML 输出流
JavaScript 能够创建动态 HTML 内容:
document.write()
可用于直接写入 HTML 输出流:
<!DOCTYPE html>
<html>
<body><script>
document.write(Date());
</script></body>
</html>
改变 HTML 内容
修改 HTML 文档内容最简单的方法是,使用 innerHTML
属性。
如需修改 HTML 元素的内容,请使用此语法:
<!DOCTYPE html>
<html><body><p id="p10">"hello world!";</p><script>document.getElementById("p10").innerHTML ="hello kitty!";</script></body>
</html>
改变属性的值
如需修改 HTML 属性的值,请使用如下语法:
document.getElementById(id).attribute = new value
<!DOCTYPE html>
<html><body><img id="demo1" src="/home/ss/learn/node_learn/2023-08-05 12-41-26 的屏幕截图.png"></body><script>document.getElementById("demo1").src = "/home/ss/learn/node_learn/2023-08-05 12-43-54 的屏幕截图.png";</script>
</html>
JavaScript 表单
JavaScript 表单验证
HTML 表单验证可以通过 JavaScript 完成。
如果表单域 (fname) 为空,该函数会提示一条消息,并返回 false,以防止表单被提交:
<!DOCTYPE html>
<html>
<head>
<script>
function validateForm() {let x = document.forms["myForm"]["fname"].value;if (x == "") {alert("Name must be filled out");return false;}
}
</script>
</head>
<body><h1>JavaScript 验证</h1><form name="myForm" action="/demo/html/action_page.php" onsubmit="return validateForm()" method="post">Name: <input type="text" name="fname"><input type="submit" value="Submit">
</form></body>
</html>
JavaScript 可以验证数字输入
<!DOCTYPE html>
<html>
<body><h1>JavaScript 验证</h1><form action="/demo/html/action_page.php" method="post"><input type="text" name="fname" required><input type="submit" value="提交">
</form><p>如果您点击提交,而不填写文本字段,浏览器将显示错误消息。</p></body>
</html>
JavaScript HTML DOM - 改变 CSS
<html>
<body><p id="p2">Hello World!</p><script>
document.getElementById("p2").style.color = "blue";
</script><p>上面的段落已被脚本改变。</p></body>
</html>
使用事件
HTML DOM 允许您在事件发生时执行代码。
当“某些事情”在 HTML 元素上发生时,浏览器会生成事件:
- 点击某个元素时
- 页面加载时
- 输入字段被更改时
您将在本教程的下一章学到更多有关事件的知识。
本例会在用户点击按钮时,更改 id="id1" 的 HTML 元素的样式:
<!DOCTYPE html>
<html>
<body><h1 id="id1">我的标题</h1><button type="button"
onclick="document.getElementById('id1').style.color = 'red'">
单击我!</button></body>
</html>
JavaScript HTML DOM 动画
为了演示如何通过 JavaScript 来创建 HTML 动画,我们将使用一张简单的网页
<!DOCTYPE html>
<html>
<body><h1>我的第一部 JavaScript 动画</h1><div id="animation">我的动画在这里。</div></body>
</html>
为元素添加样式
应该通过 style = "position: relative
" 创建容器元素。
应该通过 style = "position: absolute
" 创建动画元素。
<!Doctype html>
<html>
<style>
#container {width: 400px;height: 400px;position: relative;background: yellow;
}
#animate {width: 50px;height: 50px;position: absolute;background: red;
}
</style>
<body><h1>我的第一个 JavaScript 动画</h1><div id="container">
<div id="animate"></div>
</div></body>
</html>
动画代码
JavaScript 动画是通过对元素样式进行渐进式变化编程完成的。
这种变化通过一个计数器来调用。当计数器间隔很小时,动画看上去就是连贯的。
基础代码是:
<!DOCTYPE html>
<html>
<style>
#container {width: 400px;height: 400px;position: relative;background: yellow;
}
#animate {width: 50px;height: 50px;position: absolute;background-color: red;
}
</style>
<body><p><button onclick="myMove()">单击我</button></p> <div id ="container"><div id ="animate"></div>
</div><script>
function myMove() {var elem = document.getElementById("animate"); var pos = 0;var id = setInterval(frame, 5);function frame() {if (pos == 350) {clearInterval(id);} else {pos++; elem.style.top = pos + "px"; elem.style.left = pos + "px"; }}
}
</script></body>
</html>
JavaScript HTML DOM 事件
对事件作出反应
JavaScript 能够在事件发生时执行,比如当用户点击某个 HTML 元素时。
为了在用户点击元素时执行代码,请向 HTML 事件属性添加 JavaScript 代码:
HTML 事件的例子:
- 当用户点击鼠标时
- 当网页加载后
- 当图像加载后
- 当鼠标移至元素上时
- 当输入字段被改变时
- 当 HTML 表单被提交时
- 当用户敲击按键时
<!DOCTYPE html>
<html>
<body><h1 onclick="this.innerHTML='谢谢!'">请点击此文本!</h1></body>
</html>
<!DOCTYPE html>
<html>
<body><h1 onclick="changeText(this)">点击此文本!</h1><script>
function changeText(id) { id.innerHTML = "Hello:)";
}
</script></body>
</html>
<!DOCTYPE html>
<html>
<body><p>请点击“试一试”按钮,以执行 displayDate() 函数。</p><button id="myBtn">试一试</button><p id="demo"></p><script>
document.getElementById("myBtn").onclick = displayDate;function displayDate() {document.getElementById("demo").innerHTML = Date();
}
</script></body>
</html>
onload 和 onunload 事件
当用户进入后及离开页面时,会触发 onload
和 onunload
事件。
onload
事件可用于检测访问者的浏览器类型和浏览器版本,然后基于该信息加载网页的恰当版本。
onload
和 onunload
事件可用于处理 cookie。
<!DOCTYPE html>
<html>
<body onload="checkCookies()"><p id="demo"></p><script>
function checkCookies() {var text = "";if (navigator.cookieEnabled == true) {text = "Cookie 已启用";} else {text = "Cookie 未启用";}document.getElementById("demo").innerHTML = text;
}
</script></body>
</html>
onchange 事件
onchange
事件经常与输入字段验证结合使用。
下面是一个如何使用 onchange
的例子。当用户改变输入字段内容时,会调用 upperCase() 函数。
<!DOCTYPE html>
<html>
<head>
<script>
function myFunction() {var x = document.getElementById("fname");x.value = x.value.toUpperCase();
}
</script>
</head>
<body>请输入您的名字:<input type="text" id="fname" onchange="myFunction()"><p>离开输入字段时,会触发一个函数,将输入文本转换为大写。</p></body>
</html>
onmouseover 和 onmouseout 事件
onmouseover
和 onmouseout
事件可用于当用户将鼠标移至 HTML 元素上或移出时触发某个函数:
<!DOCTYPE html>
<html>
<body><div onmouseover="mOver(this)" onmouseout="mOut(this)"
style="background-color:#D94A38;width:120px;height:20px;padding:40px;">
请把鼠标移上来</div><script>
function mOver(obj) {obj.innerHTML = "谢谢您"
}function mOut(obj) {obj.innerHTML = "请把鼠标移上来"
}
</script></body>
</html>
onmousedown, onmouseup 以及 onclick 事件
onmousedown
, onmouseup
以及 onclick
事件构成了完整的鼠标点击事件。先当鼠标按钮被点击时,onmousedown
事件被触发;然后当鼠标按钮被释放时,onmouseup
事件被触发;最后,当鼠标点击完成后,onclick
事件被触发。
<!DOCTYPE html>
<html>
<body><div onmousedown="mDown(this)" onmouseup="mUp(this)"
style="background-color:#D94A38;width:90px;height:20px;padding:40px;">
点击鼠标</div><script>
function mDown(obj) {obj.style.backgroundColor = "#1ec5e5";obj.innerHTML = "松开鼠标";
}function mUp(obj) {obj.style.backgroundColor="#D94A38";obj.innerHTML="谢谢您";
}
</script></body>
</html>
JavaScript HTML DOM 事件监听程序
<!DOCTYPE html>
<html>
<body><h2>JavaScript addEventListener()</h2><p>此示例使用 addEventListener() 方法将 click 事件附加到按钮。</p><button id="myBtn">试一试</button><p id="demo"></p><script>
document.getElementById("myBtn").addEventListener("click", displayDate);function displayDate() {document.getElementById("demo").innerHTML = Date();
}
</script></body>
</html>
element.addEventListener(event, function, useCapture);
第一个参数是事件的类型(比如 "click" 或 "mousedown")。
第二个参数是当事件发生时我们需要调用的函数。
第三个参数是布尔值,指定使用事件冒泡还是事件捕获。此参数是可选的。
注意:请勿对事件使用 "on" 前缀;请使用 "click" 代替 "onclick"。
向相同元素添加多个事件处理程序
<!DOCTYPE html>
<html>
<body><h1>JavaScript addEventListener()</h1><p>此示例使用 addEventListener() 方法将两个 click 事件添加到同一按钮。</p><button id="myBtn">试一试</button><script>
var x = document.getElementById("myBtn");
x.addEventListener("click", myFunction);
x.addEventListener("click", someOtherFunction);function myFunction() {alert ("Hello World!");
}function someOtherFunction() {alert ("此函数也被执行了!");
}
</script></body>
</html>
向 Window 对象添加事件处理程序
addEventListener()
允许您将事件监听器添加到任何 HTML DOM 对象上,比如 HTML 元素、HTML 对象、window 对象或其他支持事件的对象,比如 xmlHttpRequest 对象。
<!DOCTYPE html>
<html>
<body><h1>JavaScript addEventListener()</h1><p>此例在 window 对象上使用 addEventListener() 方法。</p><p>尝试调整此浏览器窗口的大小以触发“resize”事件处理程序。</p><p id="demo"></p><script>
window.addEventListener("resize", function(){document.getElementById("demo").innerHTML = Math.random();
});
</script></body>
</html>
事件冒泡还是事件捕获?
在 HTML DOM 中有两种事件传播的方法:冒泡和捕获。
事件传播是一种定义当发生事件时元素次序的方法。假如 <div> 元素内有一个 <p>,然后用户点击了这个 <p> 元素,应该首先处理哪个元素“click”事件?
在冒泡中,最内侧元素的事件会首先被处理,然后是更外侧的:首先处理 <p> 元素的点击事件,然后是 <div> 元素的点击事件。
在捕获中,最外侧元素的事件会首先被处理,然后是更内侧的:首先处理 <div> 元素的点击事件,然后是 <p> 元素的点击事件。
在 addEventListener() 方法中,你能够通过使用“useCapture”参数来规定传播类型:
removeEventListener() 方法
removeEventListener()
方法会删除已通过 addEventListener()
方法附加的事件处理程序:
<!DOCTYPE html>
<html>
<head>
<style>
#myDIV {background-color: coral;border: 1px solid;padding: 50px;color: white;font-size: 20px;
}
</style>
</head>
<body><h1>JavaScript removeEventListener()</h1><div id="myDIV"><p>这个 div 元素有一个 onmousemove 事件处理程序,每次在这个橙色字段中移动鼠标时都会显示一个随机数。</p><p>单击按钮以删除 div 的事件处理程序。</p><button onclick="removeHandler()" id="myBtn">删除</button>
</div><p id="demo"></p><script>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);function myFunction() {document.getElementById("demo").innerHTML = Math.random();
}function removeHandler() {document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
}
</script></body>
</html>
JavaScript HTML DOM 导航
DOM 节点
根据 W3C HTML DOM 标准,HTML 文档中的所有事物都是节点:
- 整个文档是文档节点
- 每个 HTML 元素是元素节点
- HTML 元素内的文本是文本节点
- 每个 HTML 属性是属性节点
- 所有注释是注释节点
节点关系
节点树中的节点彼此之间有一定的等级关系。
- 术语(父、子和同胞,parent、child 以及 sibling)用于描述这些关系。
- 在节点树中,顶端节点被称为根(根节点)。
- 每个节点都有父节点,除了根(根节点没有父节点)。
- 节点能够拥有一定数量的子
- 同胞(兄弟或姐妹)指的是拥有相同父的节点。
<html><head><title>DOM 教程</title></head><body><h1>DOM 第一课</h1><p>Hello world!</p></body></html>
从以上的 HTML 中您能读到以下信息:
- <html> 是根节点
- <html> 没有父
- <html> 是 <head> 和 <body> 的父
- <head> 是 <html> 的第一个子
- <body> 是 <html> 的最后一个子
子节点和节点值
DOM 处理中的一种常见错误是认为元素节点中包含文本。
<!DOCTYPE html>
<html>
<body><h1 id="id01">我的第一张网页</h1>
<p id="id02"></p><script>
document.getElementById("id02").innerHTML = document.getElementById("id01").innerHTML;
</script></body>
</html>
<html>
<body><h1 id="id01">我的第一张页面</h1>
<p id="id02">Hello!</p><script>document.getElementById("id02").innerHTML = document.getElementById("id01").firstChild.nodeValue;
</script></body>
</html>
<html>
<body><h1 id="id01">我的第一张页面</h1>
<p id="id02">Hello!</p><script>document.getElementById("id02").innerHTML = document.getElementById("id01").childNodes[0].nodeValue;
</script></body>
</html>
<html>
<body><p>Hello World!</p>
<div>
<p>DOM 很有用!</p>
<p>本例演示 <b>document.body</b> 属性。</p>
</div><script>alert(document.body.innerHTML);
</script></body>
</html>
HTML DOM 元素(节点)
添加和删除节点(HTML 元素)
创建新 HTML 元素(节点)
如需向 HTML DOM 添加新元素,您必须首先创建这个元素(元素节点),然后将其追加到已有元素。
<!DOCTYPE html>
<html>
<body><div id="div1">
<p id="p1">这是一段文字。</p>
<p id="p2">这是另一段文字。</p>
</div><script>
var para = document.createElement("p");
var node = document.createTextNode("这是新的文本。");
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
</script></body>
</html>
删除已有 HTML 元素
如需删除 HTML 元素,请使用 remove()
方法:
<!DOCTYPE html>
<html>
<body><h1>JavaScript HTML DOM</h1><p>删除 HTML 元素:</p><div>
<p id="p1">This is a paragraph.</p>
<p id="p2">This is another paragraph.</p>
</div><button onclick="myFunction()">删除元素</button><script>
function myFunction() {
document.getElementById("p1").remove();
}
</script></body>
</html>
<!DOCTYPE html>
<html>
<body><div id="div1">
<p id="p1">这是一段文字。</p>
<p id="p2">这是另一段文字。</p>
</div><script>
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.removeChild(child);
</script></body>
</html>
替换 HTML 元素
如需替换元素的,请使用 replaceChild()
方法:
<!DOCTYPE html>
<html>
<body><div id="div1">
<p id="p1">这是一段文字。</p>
<p id="p2">这是另一段文字。</p>
</div><script>
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
var para = document.createElement("p");
var node = document.createTextNode("这是新的文本。");
para.appendChild(node);
parent.replaceChild(para,child);
</script></body>
</html>
HTML DOM 节点列表
NodeList 对象是从文档中提取的节点列表(集合)。
NodeList 对象与 HTMLCollection 对象几乎相同。
如使用 getElementsByClassName()
方法,某些(老的)浏览器会返回 NodeList 对象而不是 HTMLCollection。
所有浏览器都会为 childNodes
属性返回 NodeList 对象。
大多数浏览器会为 querySelectorAll()
方法返回 NodeList 对象。
下面的代码选取文档中的所有 <p> 节点:
<!DOCTYPE html>
<html>
<body><h1>JavaScript HTML DOM</h1><p>Hello World!</p><p>Hello China!</p><p id="demo"></p><script>
var myNodelist = document.querySelectorAll("p");
document.getElementById("demo").innerHTML =
"第二段的 innerHTML 是:" +
myNodelist[1].innerHTML;
</script></body>
</html>
HTML DOM Node List 长度
length
属性定义节点列表中的节点数:
<!DOCTYPE html>
<html>
<body><h1>JavaScript HTML DOM</h1><p>Hellow World!</p><p>Hello China!</p><p id="demo"></p><script>
var myNodelist = document.querySelectorAll("p");
document.getElementById("demo").innerHTML =
"此文档包含 " + myNodelist.length + " 段文字。";
</script></body>
</html>