RYF javascript笔记4


5. DOM

5.1 document对象

5.1.1 DOM的含义

文档对象模型(Document Object Model)。

5.1.2 document对象概述

document对象是文档的根节点,window.document属性就指向它。

document.childNodes属性返回该对象的所有子节点。

一般来说,document对象的第一个子节点是document.doctype,第二个子节点是document.documentElement。

5.1.3 document对象的属性

5.1.3.1 文档信息属性

title:文档的标题。
lastModified:文档文件的上一次修改时间。
referrer:文档的访问来源。
URL:文档的URL。

5.1.3.2 指向其他节点或对象的属性

doctype:文档类型节点。
documentElement:html元素节点。
head:head元素节点。
body:body元素节点。

5.1.3.3 指向特定元素集合的属性

document.forms :所有的form元素。
document.images:所有的img元素。
document.links:所有的a元素。
document.scripts:所有的script元素。
document.styleSheets:所有的link或者style元素。

5.1.3.4 implementation属性

该属性指向一个对象,提供浏览器支持的模块信息,它的hasFeature方法返回一个布尔值,表示是否支持某个模块。

document.implementation.hasFeature('MutationEvents','2.0') // true

5.1.4 document对象的方法

5.1.4.1 document.write()

document.write方法用于向页面写入内容。如果在页面已经渲染完成的情况下调用这个方法,会把原有的页面全部抹去,等于是在一个新建的页面上写入内容。
所以,一般document.write只能在页面渲染的过程中使用。

<div> 
  <script type="text/javascript"> 
    document.write("<h1>Main title</h1>") 
  </script> 
</div>

5.1.4.2 querySelector(),getElementById()

querySelector使用CSS选择器语法(还可以接受复杂的CSS选择器),
getElementById使用id属性(更高效)。
找不到返回null。

document.querySelector('#myElement')
document.getElementById('myElement')

5.1.4.2 querySelectorAll(),getElementsByTagName(),getElementsByClassName()

document.querySelectorAll('DIV:not(.ignore)');
document.getElementsByTagName('li')
document.getElementsByClassName('liClass')

5.1.4.3 getElementsByName()

用于选择拥有name属性的HTML元素,比如form、img、frame、embed和object。返回值是一组对象

var forms = document.getElementsByName("x");
forms[0].tagName // "FORM"

5.1.4.4 createElement(),createTextNode()

createElement方法用来生成元素节点,参数是元素节点的tagName属性
createTextNode方法用来生成文本节点。参数是要生成的文本节点的内容。

var elementNode = document.createElement('div');
var textNode = document.createTextNode('Hi');

5.1.4.5 hasFocus()

返回布尔值,表示当前文档之中是否有元素被激活或获得焦点。

focused = document.hasFocus();

5.2 Node对象

5.2.1 Node节点对象

DOM就是由Node组成的。Node分外:

  1. DOCUMENT_NODE 文档节点(window.document)、
  2. ELEMENT_NODE 元素节点
  3. ATTRIBUTE_NODE 属性节点(比如class="right")、
  4. TEXT_NODE 文本节点
  5. DOCUMENT_FRAGMENT_NODE 文档碎片节点
  6. DOCUMENT_TYPE_NODE 文档类型节点。

浏览器原生提供一个Node对象,上面所有类型的节点都是Node对象派生出来的,它们都继承了Node的属性和方法。

对于HTML文档,节点有以下类型:

5.2.1.1 Node对象的属性

1、nodeName属性和nodeType属性

nodeName节点的名称,nodeType节点的常数值。

类型 nodeName nodeType
ELEMENT_NODE 大写的HTML元素名 1
ATTRIBUTE_NODE 等同于Attr.name 2
TEXT_NODE #text 3

2、nodeValue属性

Text节点的nodeValue属性返回文本内容,其他的节点都返回null。

3、childNodes属性和children属性
childNodes返回所有子节点
children返回成员为HTML元素类型的子节点

4、指向其他节点的属性
firstChild:第一个子节点。
lastChild:最后一个子节点。
。。。

5.2.1.2 Node对象的方法

appendChild()
cloneNode()
compareDocumentPosition()
contains()
hasChildNodes()
insertBefore()
isEqualNode()
removeChild()
replaceChild()

5.2.2 Element对象

5.2.2.1 属性

每个HTML标签,都会转化成一个Element对象节点。
所有的Element节点的nodeType属性都是1,但是不同标签生成的节点是不一样的。

1、innerHTML属性,outerHTML属性,textContent属性,innerText属性,outerText属性

2、tagName属性

tagName属性返回该节点的HTML标签名,与nodeName属性(大写)相同。

document.querySelector('a').tagName // A

3、attributes属性

var atts = document.querySelector('a').attributes;

for(var i=0; i< atts.length; i++){
    console.log(atts[i].nodeName +'='+ atts[i].nodeValue);
}

5.2.2.2 className属性和classList属性

都返回HTML元素的class属性。

<div class="one two three" id="myDiv"></div>

document.getElementById('myDiv').className
// "one two three"

document.getElementById('myDiv').classList
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }

classList对象有一系列方法。

add():增加一个class。
remove():移除一个class。
contains():检查该DOM元素是否包含某个class。
toggle():将某个class移入或移出该DOM元素。
item():返回列表中某个特定位置的class。
toString():将class的列表转为字符串。

比较className和classList写法的区别。

document.getElementById('foo').className += 'bold';
document.getElementById('foo').classList.add('bold');
document.getElementById('foo').classList.remove('bold');
document.getElementById('foo').className = 
  document.getElementById('foo').className.replace(/^bold$/, '');

5.2.2.3 html元素

html元素是网页的根元素,document.documentElement就指向它。

1、clientWidth属性,clientHeight属性

返回视口(用户当前能够看见的那部分,不包括滚动条)的大小。

他两基本上与window.innerWidth和window.innerHeight同义。只有一个区别,后者包括了滚动条。

(2)offsetWidth属性,offsetHeight属性

这两个属性返回html元素的宽度和高度,即网页的总宽度和总高度。

5.2.2.4 dataset属性

dataset属性用于操作HTML标签的data-*属性。

<div id="myDiv" data-id="myId"></div>

var id = document.getElementById("myDiv").dataset.id;
document.getElementById("myDiv").dataset.id = "hello"; //赋值或添加
delete document.getElementById("myDiv").dataset.id //删除

注意:dataset属性使用骆驼拼写法表示属性名,这意味着data-hello-world会用dataset.helloWorld表示。而如果此时存在一个data-helloWorld属性,该属性将无法读取。

5.2.2.5 页面位置相关属性

1、offsetParent属性、offsetTop属性和offsetLeft属性
2、clientWidth属性和clientHeight属性
3、scrollHeight属性和scrollWidth属性
4、scrollTop属性和scrollLeft属性

5.2.2.6 style属性

style属性用来读写页面元素的行内CSS属性,详见 5.4

5.2.2.7 Element对象的方法

5.2.2.8 setAttribute(),removeAttribute()

<div id="foo"></div>
document.getElementById('foo').setAttribute('role', 'button');
//<div id="foo" role="button"></div>
document.getElementById('foo').removeAttribute('role');

5.2.2.9 insertAdjacentHTML()

将一段字符串,作为HTML或XML对象,插入DOM。通常用这个方法添加新节点。

document.getElementById("box2").insertAdjacentHTML('beforebegin', '<div><p>This gets inserted.</p></div>');

第一个是插入的位置,第二个是插入的节点字符串。
关于插入的位置,可以取值:beforebegin、afterbegin、beforeend、afterend。

5.2.2.10 getBoundingClientRect方法

5.2.2.11 table元素

表格有一些特殊的DOM操作方法。

insertRow():在指定位置插入一个新行(tr)。
deleteRow():在指定位置删除一行(tr)。
insertCell():在指定位置插入一个单元格(td)。
deleteCell():在指定位置删除一个单元格(td)。

5.2.3 Text节点

文本对应Text节点,哪怕只有一个空格,也会形成文本节点。

5.3 DOM事件

5.3.1 概述

DOM定义了一些事件,并且允许开发者通过以下3个方式指定事件的回调函数。

1、HTML属性定义

<body onclick="console.log('触发事件')">

2、Element对象的事件属性

div.onclick = function(event){
    console.log('触发事件');
};

3、addEventListener方法,removeEventListener方法

button.addEventListener('click', 
        function(){console.log('Hello world');}, 
        false);

其中第3个参数默认为false,表示回调函数只在冒泡阶段被触发。

5.3.2 事件的传播

5.3.2.1 传播的三个阶段

第一阶段:从文档的根元素(html元素)传导到目标元素,称为“捕获阶段”。
第二阶段:在目标元素上触发,称为“目标阶段”。
第三阶段:从目标元素传导回文档的根元素,称为“冒泡阶段”。

浏览器总是假定click事件的目标对象,是嵌套最深的那个元素。

5.3.2.2 事件的代理

由于事件有冒泡阶段,因此可以把子元素的回调函数定义在父元素上统一处理。这种方法叫做事件的代理。

var ul = document.querySelector('ul');
ul.addEventListener('click', function(event) {
   if (event.target.tagName.toLowerCase() === 'li') {
      // some code
   }
});

5.3.3 事件的类型

DOM支持多种事件。

5.3.3.1 用户界面事件

1、load事件,error事件
对资源的加载,成功了触发load事件,失败了触发error事件。
error事件不会冒泡。以防止引发父元素的error事件回调函数。

2、unload事件
卸载资源时触发。

3、beforeunload事件
在用户关闭网页时触发。它会自动跳出一个确认对话框,如果用户点击“取消”按钮,网页就不会关闭。

window.onbeforeunload = function() {
  if (textarea.value != textarea.defaultValue) {
    return '你确认要离开吗?';
  }
};

4、resize事件
改变浏览器窗口大小时触发。

5、abort事件
资源在加载成功前停止加载时触发该事件,主要发生在element、XMLHttpRequest、XMLHttpRequestUpload对象。

6、scroll事件
用户滚动窗口或某个元素时触发该事件,主要发生在element、document、window对象。

7、contextmenu事件
用户鼠标右击某个元素时触发,主要发生在element对象。

5.3.3.2 焦点事件

事件名称 涵义 事件的目标
blur 元素丧失焦点 Element(除了body和frameset元素) Document
focus 元素获得焦点 Element(除了body和frameset元素) Document
focusin 元素即将获得焦点,在focus之前触发 Element
focusout 元素即将丧失焦点,在blur之前触发 Element

5.3.3.3 表单事件

1、change事件
一些特定的表单元素(比如文本框和输入框)失去焦点、并且值发生变化时触发。

2、reset事件
表单重置(reset)时触发。

3、submit事件
表单提交(submit)时触发。

4、select事件
用户在文本框或输入框中选中文本时触发。

5.3.3.4 鼠标事件

1、click事件
它的定义是同一个位置完成一次mousedown和mouseup动作。它们的触发顺序是:mousedown,mouseup,最后click。

可以利用click事件进行CSRF(跨站请求伪造Cross-site request forgery)攻击。

2、dblclick事件
用户在element、document、window对象上用鼠标双击时触发。该事件会在mousedown、mouseup、click之后触发。

3、mousedown事件

4、mouseup事件
5、mouseenter事件
该事件与mouseover事件相似,区别在于mouseenter事件不会冒泡,而且当鼠标移出子元素的边界、当仍在父元素之中时,它不会在父元素上触发。

6、mouseleave事件
该事件与mouseout事件类似,区别在于mouseleave事件不会冒泡,而且要等到鼠标离开该元素本身和它的所有子元素时才触发。

7、mousemove事件
当鼠标持续移动时,该事件会连续触发。(性能)

8、mouseout事件

9、mouseover事件

10、wheel事件
用户滚动鼠标的滚轮时触发。

5.3.3.5 键盘事件

1、keydown事件

2、keypress事件
用户按下某个键时触发。如果用户一直按着,这个事件就持续触发。

3、keyup事件

//捕捉用户按下Ctrl+H键的代码
document.addEventListener('keydown', function(event) {
  if (event.ctrlKey && event.which === 72) {
    // open help widget
  }
});

5.3.3.6 document对象的特有事件

1、readystatechange
在readyState属性发生变化时触发。它的发生对象是document和XMLHttpRequest对象。

2、DOMContentLoaded
在网页解析完成时触发,此时各种外部资源(resource)还没有被完全下载。也就是说,这个事件比load的触发早得多。

5.3.3.7 拖拉事件

1、drag
drag事件在源对象被拖拉过程中触发。

2、dragstart,dragend
dragstart事件在用户开始用鼠标拖拉某个对象时触发,dragend事件在结束拖拉时触发。

3、dragenter,dragleave
dragenter事件在源对象拖拉进目标对象后,在目标对象上触发。dragleave事件在源对象离开目标对象后,在目标对象上触发。

4、dragover事件
dragover事件在源对象拖拉过另一个对象上方时,在后者上触发。

5、drop事件
当源对象被拖拉到目标对象上方,用户松开鼠标时,在目标对象上触发drop事件。

5.3.3.8 CSS事件

transitionEnd
animationstart,animationend,animationiteration

5.3.4 event对象

当事件发生以后,会生成一个事件对象event,在DOM中传递,也被作为参数传给回调函数。
IE8及以下版本,这个事件需要通过window对象的event属性读取,所以要获取这个对象,往往写成下面这样。

function myEventHandler(event) {
    var actualEvent = event || window.event;
    // handle actualEvent
}

5.3.4.1 event对象的属性

type:返回一个字符串,表示事件的名称。
target:返回一个Element节点,表示事件起源的那个节点。
keyCode:返回按键对应的ASCII码。
ctrlKey:返回一个布尔值,表示是否按下ctrl键。

5.3.4.2 click事件

click的event还包括:

pageX,pageY:点击位置相对于html元素的坐标,单位为CSS像素。
clientX,clientY:点击位置相对于视口(viewport)的坐标,单位为CSS像素。
screenX,screenY:点击位置相对于设备显示屏幕的坐标,单位为设备硬件的像素。

5.3.4.3 event对象的方法

5.3.5 自定义事件

用户还可以自定义事件,然后手动触发。

$('some-element').trigger('my-custom-event');

这是jQuery定义的trigger事件,它会层层向上冒泡。冒泡过程中,如果有一个元素定义了该事件的回调函数,该回调函数就会触发。

也可以使用浏览器原生方法创造自定义事件。

5.4 CSS操作

5.4.1 DOM元素的CSS操作

5.4.1.1 HTML元素的style属性

操CSS的最简单方法:通过DOM的getAttribute、setAttribute和removeAttribute方法。

div.setAttribute('style','background-color:red;');

5.4.1.2 style对象

DOM还提供style属性,指向一个对象(简称style对象),用来读写元素的行内CSS样式。

var divStyle = document.querySelector('div').style;
divStyle.backgroundColor = 'red';
divStyle.width = '100px';

1、style对象的属性名
它等于:去掉CSS规则名的横杠,横杠后的第一个字母大写。
如:background-color 改为 backgroundColor。
如果CSS规则名是js保留字,则改为“css”+规则名。如:float 改为 cssFloat。

注意,style对象的属性值都是字符串且包括单位。所以,divStyle.width不能设置为100,而要设置为'100px'。

2、style对象的cssText属性
用来读写或删除整个style属性。

divStyle.cssText = 'background-color:red;height:100px;width:100px;';

3、CSS模块的侦测
“CSS模块的侦测”是判断当前浏览器是否支持某个模块。

常用方法是,判断DOM元素的style对象的某个属性值是否为字符串。

typeof element.style.animationName === 'string';
typeof element.style.transform === 'string';

有时候,需要把不同浏览器的CSS规则前缀也考虑进去。

typeof document.getElementById("content").style['-webkit-animation'] === 'string'

4、style对象的方法
setPropertyValue(propertyName,value) // 写
getPropertyValue(propertyName) // 读
removeProperty(propertyName) // 删除

5、style对象的animation-play-state属性
用来控制暂停动画的播放。该属性需要加上浏览器前缀。

element.style.webkitAnimationPlayState = "paused";
element.style.webkitAnimationPlayState = "running";

5.4.1.3 CSS伪元素

CSS伪元素是通过CSS向DOM添加的元素,主要方法是通过“:before”和“:after”生成伪元素,然后用content属性指定伪元素的内容。

5.4.1.4 CSS事件

动画(animation)事件
过渡(transition)事件

5.4.2 样式表

5.4.2.1 获取样式表

document对象的styleSheets属性,包含一个类似数组的对象,里面是当前文档所有的link元素(指向样式表)和style元素。

var sheets = document.styleSheets;
var sheet = document.styleSheets[0];

5.4.2.2 样式表对象

样式表对象有许多属性和方法。

cssRules属性指向一个类似数组的对象,它的每个成员就是一条CSS规则,其cssText属性就是CSS规则的字符串。

var sheet = document.querySelector('#styleElement').sheet;
sheet.cssRules[0].cssText
// "body { background-color: red; margin: 20px; }"

insertRule和deleteRule方法 用于插入和删除CSS规则。
disabled属性 用于打开或关闭一张样式表。

5.4.2.3 添加样式表

添加内置样式表,就是在文档中添加style节点。
添加外部样式表,就是在文档中添加link节点。

var linkElm = document.createElement('link');
linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('href', 'reset-min.css');

document.head.appendChild(linkElm);

5.4.3 window.getComputedStyle方法

getComputedStyle方法返回一个HTML元素的最终样式信息的对象。

5.5 拖放操作

5.5.1 拖放操作

5.5.1.1 网页元素的draggable属性

draggable用于标识元素是否可以拖动。
在大多数浏览器中,a元素和img元素默认是可以拖放的。

5.5.1.2 事件

5.5.2 自定义网页元素(Custom Element)

通过JavaScript可以自定义网页元素。使用前,用document对象的registerElement方法登记该元素。

5.6 Mutation Observer

Mutation Observer(变动观察器)是监视DOM变动的接口。当DOM对象树发生任何变动的时候,Mutation Observer会得到通知。

它与事件有一个本质不同:事件是同步触发;Mutation Observer则是异步触发。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,499评论 6 13
  • 第1章 认识JS JavaScript能做什么?1.增强页面动态效果(如:下拉菜单、图片轮播、信息滚动等)2.实现...
    mo默22阅读 1,171评论 0 5
  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,721评论 0 8
  • 下班路上,收到大学好友的微信,问我是否真的已经从律师事务所辞职,又问我如果在读的研究生学校不满意,是否有再考的价值...
    宿隔阅读 315评论 0 4
  • 为奴十二载 平权无尽时 (黑人运动) 感觉 平 对 为 念起来不台好听,用什么说法比较好呢?争权? 梦归四千天 这...
    虫二宝宝阅读 674评论 11 2