整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

DOM 操作之属性操作

DOM 操作之属性操作

章目标


  • 掌握基本属性的使用
  • 掌握 textContent 和 innerHTML 的区别
  • 掌握表单属性的使用
  • 掌握自定义属性的使用

本章任务


  • 能够完成美女相册案例
  • 能够完成登录验证功能
  • 能够完成注册页面的同意协议单选框功能
  • 能够完成小图切换大图功能

属性操作


在美女画廊的案例中,我们需要获取到 img 元素,并修改 img 中显示的图片还需要获取到页面上的 p 元素修改 p 元素中显示的内容,本章中我们就来学习如何修改元素的相关属性。

基本属性


基本属性指的是 HTML 标签本身所具有的属性(HTML 中的标准属性),这些属性在浏览器把 HTML 文档生成 DOM 树的时候会自动设置为 DOM 树上元素节点对象的属性。


常用的基本属性:href、title、id、src。


获取或者设置基本属性的语法和步骤:

// 获取 DOM 元素
let dom=document.getElementById('id');
// 获取属性
console.log(dom.属性名称)
// 设置属性
dom.属性名称='属性值'


  • 获取元素属性的值
<a id="link" href="http://www.baidu.com">百度</a>
let link=document.getElementById('link');
// 获取元素的属性
console.log(link.id); // "link"
console.log(link.href); // "http://www.baidu.com/"
  • 设置元素属性的值
let link=document.getElementById('link');
// 设置元素的属性
link.title='google';
link.href='http://www.google.com';

你可以尝试下点击按钮修改 img 标签的图片(修改 src 属性)。

更改标签之间的内容


在美女画廊中我们需要更改 p 标签之间的内容,但是如何设置标签之间的内容?这里没有对应 HTML 的标准属性,但是这是一种常见的操作 DOM 对象提供了两个属性可以让我们方便的修改标签之间的内容:textContent 和 innerHTML,下面我们分别来介绍。


  • 获取或者设置标签之间的文本内容
let p=document.getElementById('p');
// 获取标签之间的内容
console.log(p.textContent);
// 设置标签之间的内容
p.textContent='Hello DOM';

你可能在其他地方见过 innerText 属性,注意这是早期 IE 中获取或者设置标签之间文本内容的属性,现代浏览器依然支持该属性,但是 DOM 中规定的标准属性是 textContent

  • 获取或者设置标签之间的 HTML 内容
let p=document.getElementById('p');
// 获取标签之间的内容
console.log(p.innerHTML)
// 设置标签之间的内容
p.innerHTML='<b>Hello DOM</b>'
  • textContent 和 innerHTML 的区别
    • textContent 获取的内容中包含 HTML 标签会被忽略
    • textContent 设置的内容中包含 HTML 标签会直接显示
    • innerHTML 获取的内容中包含 HTML 会返回标签和内容
    • innerHTML 设置的内容中包含 HTML 标签,标签会被渲染
  • HTML 中的字符实体

在网页中有一些特殊的符号,比如:< >;想要显示这些符号需要对这些内容进行转义,也就是使用 HTML 的实体。

字符实体的表示形式:

&字符实体编号;

<   // < 显示小于号
>   // > 显示大于号

显示结果

描述

实体名称

实体编号


空格

 

<

小于号

<

<

>

大于号

>

>

&

和号

&

&

"

引号

"

"

'

撇号

' (IE不支持)

'

分(cent)

¢

¢

镑(pound)

£

£

元(yen)

¥

¥

欧元(euro)

§

小节

§

§

?

版权(copyright)

©

©

?

注册商标

®

®

?

商标

×

乘号

×

×

÷

除号

÷

÷


需要记住其中的空、>、< 的字符实体名称


案例:美女画廊


  • 需求:
    • 获取一组 a 元素
    • 获取大图对应的 img 元素
    • 获取 id 为 des 的 p 元素
    • 遍历所有的 a 元素,注册 click 事件
      • 获取 a 的 href 属性并赋值给 img 的 src 属性
      • 获取当前点击的 a 的 title 值赋值给 p 的 textContent
      • 取消 a 的默认行为(见下面注意的地方)
  • 代码:
// 1. 获取一组a元素
let links=document.getElementsByTagName('a');
// 2. 获取id为photo的img元素
let photo=document.getElementById('photo');
// 3. 获取id为des的p元素
let p=document.getElementById('des');
// 4. 循环遍历a,注册 click事件
for (let i=0; i < links.length; i++) {
  links[i].onclick=function () {
    // 4.1 获取当前点击的a的href值赋值给 img的src属性
    photo.src=this.href;
    // 4.2 获取当前点击的a的title值赋值给p的 textContent
    p.textContent=this.title;
    // 4.3 取消a的默认跳转行为
    return false;
  };
}


注意:给 a 元素注册点击事件的时候,如果 a 元素设置了 href 属性,当触发 a 的点击事件并且事件处理函数执行完毕后,会继续执行跳转到 href 属性,这是 a 标签的默认行为。

我们想要 a 的事件处理函数不跳转,取消 a 标签的默认行为可以在事件处理函数中 return false


表单属性


JavaScript 最初的目的是用来验证用户的输入是否合法,为了实现表单元素的验证,我们需要获取用户输入的内容,这需要使用到表单元素的属性。

  • 常用的表单元素属性
    • value:用于大部分表单元素的内容获取(option除外)
    • type:可以获取input标签的类型(输入框或复选框等)
    • disabled:禁用属性
    • checked:复选框/单选框选中属性
    • selected:下拉菜单选中属性


案例:登录的验证


  • 需求:
    • 验证用户协议是否同意
    • 验证用户名必须在 3-6 位之间,包含3和6位
    • 验证密码必须大于等于8位
  • 代码:
let btn=document.querySelector('#btn');
btn.onclick=function () {
  let username=document.querySelector('#username').value;
  let pwd=document.querySelector('#pwd').value;
  let chk=document.querySelector('#chk');

  if (!chk.checked) {
    alert('请同意用户协议');
    return false;
  }
  if (username.length < 3 || username.length > 6) {
    alert('用户名应该在3-6位之间');
    return false;
  }

  if (pwd.length < 8) {
    alert('密码必须超过8位');
    return false;
  }


  alert('我去登陆了')
  // 阻止 a 的默认行为
  return false;
};

案例:注册页面

  • 需求:
    • 同意协议的复选框选中,让完成注册按钮可用
    • 同意协议的复选框不选中,让完成注册按钮不可用
  • 代码:
// 1. 获取复选框
let agree=document.querySelector('#agree');
// 2. 获取按钮
let registerBtn=document.querySelector('#registerBtn');
// 3. 给复选框注册点击事件
agree.onclick=function () {
  registerBtn.disabled=!agree.checked;
};

案例:购物车的全选功能

  • 需求:
    • 当点击全选的 checkbox
      • 让所有商品前面的 checkbox 的选中状态和全选的 checkbox 的选中状态保持一致
    • 点击商品前面的 checkbox
      • 如果所有商品全部都选中,全选 checkbox 选中
      • 如果有一个商品没有选中,全选 checkbox 不选中
  • 代码:
// 1. 获取thead中一个复选框
let allck=document.querySelector('#all');
// 2. 获取tbody中一组复选框
//【功能1】
let cks=document.querySelectorAll('tbody input[type=checkbox]');
// 3. 给thead中一个复选框注册点击事件
allck.onclick=function () {
  // 3.1 获取thead中这个复选框的checked值
  let isOk=allck.checked;
  // 3.2 循环遍历tbody中的每一个复选框,设置checked值为thead中这个复选框的checked值
  for (let i=0; i < cks.length; i++) {
    cks[i].checked=isOk;
  }
};

//【功能2】
// 1. 循环遍历tbody中每一个复选框注册点击事件
for (let i=0; i < cks.length; i++) {
  cks[i].onclick=function () {
   // 2. 获取tbody中所有的复选框的个数
    let len1=cks.length; 
    //3. 获取tbody中选中的复选框的个数
    let len2=document.querySelectorAll('tbody input:checked').length;
    // 4. 对比是否一致,若一致,则设置thead中全选框为true,否则为false
    if (len1===len2) {
      allck.checked=true;
    } else {
      allck.checked=false;
    }
  };
}

自定义属性


到这里为止我们介绍的都是标签所拥有的属性,也就是 HTML 中的标准属性,标签中还支持自定义属性,为了到达某些业务的需求,我们可以把数据存储到标签的自定义属性中。

例如:在购物车的案例中,如果我们要删除某个购物车中的商品的话,我们可以把这条数据的 id 存储到当前行的自定义属性中,例如:proId 这个属性。


自定义属性有两种用法,分别是:

  • 使用 DOM 中的标准 API 操作
    • getAttribute():获取标签行内属性
    • setAttribute():设置标签行内属性
    • removeAttribute():移除标签行内属性
    • 这组 API 也可以操作 HTML 的标准属性
  • HTML 5中新增的 data- 形式的自定义属性
    • 可以通过 元素.dataset 来获取或者设置 data- 后的自定义属性名称
    • 未来推荐使用这种方式存储数据,具有语义


// div
const d5=document.querySelector('#d5');
const d6=document.querySelector('#d6');
// 浏览器中审查元素,可以看到 d5 的 div 中会有 proId 的属性
d5.setAttribute('proId', 5)
console.log(d5.getAttribute('prodId'))

// 浏览器审查元素,可以看到 data-pro-id 的属性
// 浏览器自动把大写字母转换成了 pro-id 的形式
d6.dataset.proId=6
console.log(d6.dataset.proId)

注意:我们获取到的自定义属性或者标准属性的值都是字符串类型。

  • 注意:元素.自定义属性 的用法
<div id="d5" prodId="5">删除</div>
<div id="d6">删除</div>

浏览器在处理 HTML 的时候,会把 HTML 文档转换为浏览器内存中的 DOM 树,在转换的过程中,标签的 HTML 标准属性会被转换为 DOM 元素的属性,但是标签的自定义属性不会转换为 DOM元素的属性。

const d5=document.querySelector('#d5');
console.log(d5.proId);  // 打印的结果为 undefined

但是我们可以设置 DOM 元素的自定义属性,注意,这里的自定义属性并不会转换成 HTML 标签的自定义属性,仅仅是对象的属性,我们依然可以通过 DOM 对象,获取到该属性的值。

const d6=document.querySelector('#d6');
d6.proId=6
console.log(d6.proId);  // 打印结果为 6

案例:点击小图切换大图

<img id="small" width="80px" src="./images/small.jpg" data-big="./images/big.jpg"/>
<img id="big" src="./images/placeholder.jpg" />
let small=document.querySelector('#small');
let big=document.querySelector('#big');

small.onclick=function () {
  // 在事件处理函数中可以通过 this 获取到触发事件的元素
  // 这里的 this 就是 small 对象
  let bigImgSrc=this.dataset.big;
  big.src=bigImgSrc;
};


作业


图片切换



猜数字游戏

用JavaScript访问和操作的HTML DOM对象的例子。

Document 对象

  • 使用 document.write() 输出文本

  • 使用 document.write() 输出 HTML

  • 返回文档中锚的数目

  • 返回文档中第一个锚的 innerHTML

  • 返回文档中表单的数目

  • 返回文档中第一个表单的名字

  • 返回文档中的图像数

  • 返回文档中第一个图像的ID

  • 返回文档中的链接数

  • 返回文档中的第一个链接的ID

  • 返回文档中的所有cookies的名称/值对

  • 返回加载的文档的服务器域名

  • 返回文档的最后一次修改时间

  • 返回加载的当前文档的URL

  • 返回文档的标题

  • 返回文档的完整的URL

  • 打开输出流,向流中输入文本

  • write() 和 writeln()的不同

  • 用指定的ID弹出一个元素的innerHTML

  • 用指定的Name弹出元素的数量

  • 用指定的tagname弹出元素的数量

Anchor 对象

  • 返回和设置链接的charset属性

  • 返回和设置链接的href属性

  • 返回和设置链接的hreflang属性

  • 返回一个锚的名字

  • 返回当前的文件和链接的文档之间的关系

  • 改变链接的target属性

  • 返回一个链接的type属性的值

Area 对象

  • 返回图像映射某个区域的替代文字

  • 返回图像映射某个区域的坐标

  • 返回一个区域的href属性的锚部分

  • 返回的主机名:图像映射的某个区域的端口

  • 返回图像映射的某个区域的hostname

  • 返回图像映射的某个区域的port

  • 返回图像映射的某个区域的href

  • 返回图像映射的某个区域的pathname

  • 返回图像映射的某个区域的protocol

  • 返回一个区域的href属性的querystring部分

  • 返回图像映射的某个区域的shape

  • 返回图像映射的某个区域的target的值

Base 对象

  • 返回页面上所有相对URL的基URL

  • 返回页面上所有相对链接的基链接

Button 对象

  • 当点击完button不可用

  • 返回一个button的name

  • 返回一个button的type

  • 返回一个button的value

  • 返回一个button所属表的ID

Form 对象

  • 返回一个表单中所有元素的value

  • 返回一个表单acceptCharset属性的值

  • 返回一个表单action属性的值

  • 返回表单中的enctype属性的值

  • 返回一个表单中元素的数量

  • 返回发送表单数据的方法

  • 返回一个表单的name

  • 返回一个表单target属性的值

  • 重置表单

  • 提交表单

Frame/IFrame 对象

  • 对iframe排版

  • 改变一个包含在iframe中的文档的背景颜色

  • 返回一个iframe中的frameborder属性的值

  • 删除iframe的frameborder

  • 改变iframe的高度和宽度

  • 返回一个iframe中的longdesc属性的值

  • 返回一个iframe中的marginheight属性的值

  • 返回一个iframe中的marginwidth属性的值

  • 返回一个iframe中的name属性的值

  • 返回和设置一个iframe中的scrolling属性的值

  • 改变一个iframe的src

Image 对象

  • 对image排版

  • 返回image的替代文本

  • 给image加上border

  • 改变image的高度和宽度

  • 设置image的hspace和vspace属性

  • 返回image的longdesc属性的值

  • 创建一个链接指向一个低分辨率的image

  • 返回image的name

  • 改变image的src

  • 返回一个客户端图像映射的usemap的值

Event 对象

  • 哪个鼠标键被点击了?

  • 被按下的键盘键的keycode?

  • 鼠标的坐标?

  • 鼠标相对于屏幕的坐标?

  • shift键被按下了吗?

  • 哪个元素被按下了?

  • 哪个事件发生了?

Option 和 Select 对象

  • 禁用和启用下拉列表

  • 获得有下拉列表的表单的ID

  • 获得下拉列表的选项数量

  • 将下拉列表变成多行列表

  • 在下拉列表中选择多个选项

  • 弹出下拉列表中所有选项

  • 弹出下拉列表中被选中的选项的索引

  • 改变下拉列表中被选中的选项的文本

  • 删除下拉列表中的选项

Table, TableHeader, TableRow, TableData 对象

  • 改变表格边框的宽度

  • 改变表格的cellpadding和cellspacing

  • 指定表格的frame

  • 为表格指定规则

  • 一个行的innerHTML

  • 一个单元格的innerHTML

  • 为表格创建一个标题

  • 删除表格中的行

  • 添加表格中的行

  • 添加表格行中的单元格

  • 单元格内容水平对齐

  • 单元格内容垂直对齐

  • 对单个单元格的内容水平对齐

  • 对单个单元格的内容垂直对齐

  • 改变单元格的内容

  • 改变单元格横跨的列数(colspan属性)

一节我们说JS主要由三部分组成:ES、DOM和BOM,接下来学生就给大家简单介绍一下他们。

ECMAScript

ECMAScript是什么

ES主要定义了基础的语法结构,以及一些内置对象。

语法就是进行沟通的规则,比如我们在代码中写“弹出提示框”,这样并不会弹出来,而写“alert()”就可以弹出来了,这就是因为ES的语法是那么规定的。对于一种编程语言来说通常都会规定定义变量、判断、循环、运算、语句集(比如函数)的定义及调用等规则,ES当然也不例外,也规定了这些内容。以前学生在单位的一次讲课中说:什么是程序,程序就是流程加顺序。虽然这种说法不够严谨,不过程序的核心应该还是流程。

ES是一种面向对象的语言,所以他的语法中还定义了很多对象相关的内容,比如最常见的this、prototype等,而且还定义了一些内置的对象,比如Number、String、Array、Math以及RegExp等。

ES的通用语法是很容易学习的,只要有点其他语言的基础,入手非常简单,这也就是一般都会觉得JS入门很容易的原因。不过ES中对象相关的语法就没那么容易了,这也是ES(或者JS)的重点和难点,学生会在后面重点进行讲解,让大家彻底掌握。

发展

ES所对应的ECMA-262标准从1997年发布的第一个版本一直到现在一共发布到了六个版本,第六版于今年(2015年)6月份刚刚发布,他的正式名称是ECMAScript 2015(简称ES2015),因为是第六版所以也有的地方叫他ECMAScript6,我们看到后知道他们是同一个东西就可以了。

ES2015中增加了很多新的特性,特别是启用了class关键字(不过并不是面向类的语言,学生会在ES2015相关章节中给大家详细分析),这样使用起来就更加方便了。不过ES的本质并没有发生变化,他依然是一种基于对象的语言,在理解了其本质之后无论哪个版本都可以非常容易地掌握,他们之间的区别无非就是一些具体语法和功能上的增强。学生后面将以现在最通用的ES5.1版为基础给大家进行讲解,最后再补充ES2015中新增的内容。

另外,我们要清楚ES只是一套标准,具体的实现还需要各个浏览器的支持,不同浏览器对ES的支持也不完全相同,而且在ES的基础上不同的浏览器也都进行了自己相应的扩充,这就造成了浏览器兼容性的问题。

DOM

我们前面说过,ES的标准化主要是为了解决各大浏览器厂商(特别是微软和网景公司)对脚本语言语法的实现不统一。不过他们在浏览器上的竞争并没有因为ES的出现而终止,微软为了占领更大的市场就在自己的Internet Explorer浏览器上加入了很多专有的属性,比如VBScript和ActiveX,而使用了这些技术的网页必须使用微软的平台和浏览器才可以正常显示,这就给开发者带来了麻烦,这时W3C的一些成员公司就提议创建一套标准将页面文档的结构暴露给脚本,从而使脚本可以统一操作页面的内容,这样最后就制定出了DOM标准。

DOM是Document Object Model的缩写,表示文档对象模型,他定义了文档对象的结构及其操作方法等内容。为什么叫对象模型呢?我们前面说过ES是一种面向对象的语言,他要操作的目标是对象,而DOM就是将html文档转换(或者对应)成ES可以操作的对象的一种模型。

DOM虽然是因为浏览器而制定的,但他现在不仅可以用在浏览器所用的Html文件中,而且还可以用到很多其他格式的文件中,比如服务端经常用来配置信息的XML文件、Flex的mxml文件以及表示矢量图的SVG格式文件等,这些都符合DOM标准。

另外,DOM主要是定义了文档(可以理解为符合相应格式的页面文件)和文档对象以及其操作方法的对应关系,而跟具体的语言无关,所以DOM不仅适用于ES,还适用于很多别的语言,比如Java中的dom4j也是DOM的一种实现。而且DOM中规定操作文档的方法都是通过接口定义的,这样不同的语言就可以按照自己的语法来进行实现了。

BOM

JS的功能并不仅限于对文档的操作,有时候还需要对浏览器直接进行操作,比如查看当前页面的url地址、控制浏览器前进、后退、以及HTML5中获取位置信息、WebSocket等都需要对浏览器进行操作,而且最简单的alert、setTimeout和setInterval也是需要浏览器来完成的。

ES对浏览器操作的处理方法和对文档操作的处理方法一样,依然是将浏览器转换为一个对象,这就是浏览器对象(Browser Object),他所对应的模型就叫浏览器对象模型(Browser Object Mode),简称BOM。

HTML5

Html5是近两年非常热的一个名词,到底什么是Html5呢?

从名字就可以看出来他是和网页相关的一个东西,而网页的三大组成部分依然是文档结构、展示和动作控制,他们所对应的技术分别是html、css和JS,前两者都属于DOM中的内容(CSS作为文档的一种特殊节点或者属性,也属于DOM的一部分,而且DOM中有专门的相关标准),JS可以对DOM进行操作。

Html5的主要贡献就是扩展了html的标签(同时也去掉了一些原先的标签),比如新增了section、article、header、footer、audio、video以及备受关注的canvas标签,当然也相应地扩展了DOM,另外Html5也对BOM进行了扩展,使得JS操作浏览器的功能更加强大,而且也促进了BOM标准化。