Javascript学习(1)

在外部文件中放置脚本有如下优势:

  • 分离了 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。但是

  1. 函数中并没有出现显示的对象创建
  2. 直接将对应的属性和方法进行赋值
  3. 没有对应的return
  4. 对应的构造函首字母需要进行大写进行保持

要使用对应的对象必须使用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 图示:

继承机制 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 表示的多重继承机制如下图所示:

继承机制 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 模型被结构化为对象树

DOM HTML 树

通过这个对象模型,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(attributevalue)改变 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返回文档的绝对基准 URI3
document.body返回 <body> 元素1
document.cookie返回文档的 cookie1
document.doctype返回文档的 doctype3
document.documentElement返回 <html> 元素3
document.documentMode返回浏览器使用的模式3
document.documentURI返回文档的 URI3
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返回文档的完整 URL1

查找 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 事件

onmousedownonmouseup 以及 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 属性是属性节点
  • 所有注释是注释节点

DOM HTML 树

节点关系

节点树中的节点彼此之间有一定的等级关系。

  • 术语(父、子和同胞,parent、child 以及 sibling)用于描述这些关系。
  • 节点树中,顶端节点被称为根(根节点)。
  • 每个节点都有父节点,除了根(根节点没有父节点)。
  • 节点能够拥有一定数量的子
  • 同胞(兄弟或姐妹)指的是拥有相同父的节点。
<html>

   <head>
       <title>DOM 教程</title>
   </head>

  <body>
       <h1>DOM 第一课</h1>
       <p>Hello world!</p>
   </body>

</html> 

DOM 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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值