浅谈DOM
DOM概念:
DOM是一个文档对象模型,是一个编程接口。通过DOM接口改变网页的内容,结构和样式。
一个页面就是一个文档
页面里面所有的标签的叫做元素。页面所有内容都是节点。
DOM把以上内容都看作对象。
getElementByid(id) 返回匹配id的元素。id必须是一个字符串形势。返回的是一个元素对象。
console.dir 打印我们返回的元素对象,更好的查看厘米的属性和方法。
getElementsByTagName() 返回带有指定标签名的对象集合。以伪数组的形式存储的。采取遍历方式获得每一个元素的内容。
通过类名获取返回的元素 — getElementsByClassName() 伪数组形式存储。
H5新增的方法:querySelector 返回指定选择器的第一个元素对象。里面的选择器要加符号
querySelectorAll()返回指定选择器的所有元素对象。
获取body元素:— document.body;
获取html元素: — document.documentElement
事件基础:触发—响应机制;
事件有三部分组成 事件源 事件类型 事件处理程序
事件源 : 事件被触发的对象 谁
事件类型 : 如何触发 什么事件 比如点击事件
事件处理程序 : 通过一个函数赋值的方式 完成
执行事件的步骤:
1、获取事件源
2、注册事件(绑定事件)
3、添加事件处理程序
利用DOM改变元素里面的内容:
element.innerText:修改元素的内容,不识别html标签,会直接将标签显示,去除空格和换行
element.innerHTML:识别html标签,保留空格和换行
这两个属性是可读写的,可以获取元素里面的内容
表单属性:
onblur失去焦点 onfocus获取焦点
innerHTML是普通盒子的属性
表单里面的值是通过value来修改的。
this.disabled = true; 表示被禁用的意思。
this 指向的是事件函数的调用者
element.style.属性名 使用DOM更改操作元素的样式属性—属性采取驼峰命名法 — 修改的样式操作,产生的行内样式,比css权重要高
element.className 类名样式操作 当修改的样式较多,功能复杂时使用。会覆盖原来的类名
让我们当前元素的类名改为其他类 this.className = ‘类名’;不需要写 点 .
既保留原来的类,有加上新的类 :
this.className = ‘原类名 新类名’;
操作元素:
操作元素的内容:innerText innerHTML
操作常见元素属性:src href title alt
操作表单元素属性:type value disabled
操作元素样式属性:element.style className
循环排他思想算法:
1、先干掉其他人,所有元素全部清除样式
2、再设置自己,给当前元素设置样式
break 退出当前for循环,这样可以提高执行效率。
element.属性 获取属性值,获取内置的属性值,元素本身自带的。
element.getAttribute(‘属性’) 程序员自己添加的属性就属于自定义属性
设置属性值:
element.属性 = ‘值’ 设置内置属性值
element.setAttribute(‘属性’,‘值’);
移除属性:
element.removeAttribute(‘属性’)
自定义属性目的:为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
H5规定自定义属性data-开头作为属性名并且赋值。
h5新增的获取自定义属性的方法
dataset是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset.index);
console.log(div.dataset[‘index’]);
获取元素的两种方式:
1、利用DOM提供的方法获取元素(逻辑性不强、繁琐)
2、利用节点层次关系获取元素(利用父子兄弟获取元素)
一个节点包含元素节点(1) 属性节点(2) 文本节点(3)
节点层级:
element.parentNode 得到的是离元素最近的父级节点(亲爸爸) 如果找不到指定的节点则返回为 null
element.childNodes 得到所有子节点 ,包含换行,空格这些元素节点和文本节点
element.childNode[index].nodeType 来分辨是什么类型的节点
如果只想要获得里面的元素节点,需要专门处理。
parentNode.children(非标准) 获取所有子元素节点,在实际开发中常用
parentNode.firstChild 返回第一个子节点,不管是什么类型的节点。
parentNode.lastChild 返回最后一个子节点
parentNode.firstElementChild 返回第一个子元素节点,找不到则返回null
parentNode.lastElementChild 返回最后一个子元素节点
但这两个方法有兼容问题,ie9+才支持
实际开发的写法
parentNode.children[0] 获取第一个子元素节点
parentNode.children[parentNode.children.length - 1] 获取最后一个子元素节点。
兄弟节点:
node.nextSibling 下一个兄弟节点 包含元素节点或者文本节点等等
node.previousSibling 上一个兄弟节点 包含元素节点或者文本节点等等
node.nextElementSibling 下一个兄弟元素节点
node.previousElementSibling 上一个兄弟元素节点
但是有兼容性问题
创建节点:
创建元素节点 — document.createElement(‘element’);
添加节点 — node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾,类似after伪元素 — node 父级 child 子级
appendChild 后面追加元素
node.insertBefore(child,指定元素) 指定放在哪个元素的前面
删除节点:
node.removeChild(child) 从DOM中删除一个子节点,返回删除的节点
this.disabled = true; 代表禁用按钮
阻止链接的跳转 — javascript:;
复制节点(克隆节点):
node.cloneNode() 方法返回调用该方法的节点的一个副本。如果括号为空或者为false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
如果括号里面写true 则是深拷贝,复制标签并且复制里面的内容
for(var k in obj){
k得到的是属性名
obj[k] 得到是属性值
}
三种动态创建元素的区别:
1、document.write() 当文档流执行完毕,它会导致页面重绘
2、element.innerHTML 用拼接字符串的方式创建,比createElemnet慢一些 。 但是不要拼接字符串,采取数组形式拼接,创建多个元素效率更高,但结构稍微复杂一些。
3、document.createElement() 结构清晰
不同浏览器下,innerHTML(数组形式拼接)效率高于 createElement
arr.join(’’) 把数组转化为字符串
DOM重点核心:我们获取过来的DOM元素是一个对象object,所以称为文档对象模型
事件高级:
一、注册事件的两种方式
利用on开头的事件onclick 有唯一性,同一个元素同一个事件只能设置应该处理函数,后面的函数会覆盖前面的。
element.addEventListener(‘click’,function(){ });里面的事件类型是字符串,必定加引号,而且不带on ,并且同一个元素同一个事件可以添加多个监听器(事件处理程序) 。IE9之前不支持,可以使用attachEvent()代替。
不提倡使用attachEvent(),并且这个方法是IE9以前的浏览器才能使用的。
eventTarget.attachEvent(‘onclick’,callback);
二、删除事件两种方式(解绑事件)
1、传统方式:element.onclick = null; 解绑
2、新方式:
div[1].addEventListener(‘click’,fn) // 里面的fn 不需要加小括号
function fn(){ div[1].removeEventListener(‘click’,fn) };
ie8以前的浏览器:
divs[2].attachEvent(‘onclick’,fn1);
function fn1(){ divs[2].detachEvent(‘onclick’,fn1)}
三、DOM事件流的三阶段
事件传播的过程称为事件流
三阶段:1、捕获阶段 2、当前目标阶段 3、冒泡阶段
注意点:1、js的代码只能执行捕获或冒泡其中一个阶段 2、onclick 和attchEvent之类的传统事件只能得到冒泡事件 3、addEventListerer第三个参数为true则事件捕获阶段调用事件处理程序,如果false表示事件冒泡阶段调用事件处理程序。
实际开发我们更加关注事件冒泡。
有些事件是没有冒泡的,比如onblur , onfocus , onmouseenter , onmouseleave
四、事件对象
事件对象写到我们侦听函数的小括号里面,当形参来看。
事件对象只有有事件才会存在,它是系统自动创建,不需要我们传递参数。
事件对象 — 是我们事件的一系列相关数据的集合跟事件相关,比如鼠标点击里面包含鼠标的相关信息,鼠标坐标等。
事件对象我们可以自己命名
事件对象有兼容性问题 ie678通过window.event 获得
兼容写法 e = e || window.event
事件对象常用的方法和属性:
e.target —点击了哪个元素就返回那个元素—返回触发事件的对象(元素)this —哪个元素绑定了事件就返回哪个元素—返回注册或绑定事件的对象(元素) 兼容处理:— var target = e.target || e.srcElement;
e.type 返回事件类型 不带‘on’
阻止默认行为(事件):让链接不跳转,或者点击按钮不提交 方法 e.preventDefault(); //dom标准写法 在低版本中ie678 属性— e.returnValue;
我们可以利用return false 也能阻止默认行为,没有兼容问题–特点就是return后面的代码不执行了,并且限于传统的注册方法。
阻止事件冒泡:事件对象里面的e.stopPropagation() 方法
非标准写法: window.e.cancelBubble = true;
五、事件委托原理
原理:不是给每个子节点单独设置事件监听器,而且事件监听器设置在父节点上,然后利用冒泡原理影响设置每个子节点
六、常用的鼠标和键盘事件
1、禁止鼠标右键菜单 contextmenu 主要控制何时显示上下文菜单 document.addEventLisenter(‘contextmenu’,function(){ e.preventDefault() })
2、禁止鼠标选中(selectstart 开始选中) document.addEventLisenter(‘selectstart’,function(){ e.preventDefault() })
鼠标事件对象MouseEvent
e.clientX 返回鼠标相对于浏览器窗口可视区的x坐标
e.clientY返回鼠标相对于浏览器窗口可视区的y坐标
e.pageX返回鼠标相对于文档页面的x坐标
e.pageY返回鼠标相对于文档页面的y坐标
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的y坐标
鼠标移动事件:mousemove 只要鼠标移动1px就会触发这个事件 注意点: 千万不要忘记给left和top加上px单位
当元素设置为绝对定位之后它是不占任何位置的
键盘事件对象 KeyboardEvent:
onkeyup 某个键盘按键被松开时触发
onkeydown某个键盘按钮被按下时触发
onkeypress某个键盘按键被按下时触发 但是它不识别功能键比如ctrl shift箭头等
keydown比keypress先执行。keydown —> keypress —> keyup
如果使用addEventListener不需要加on
键盘事件对象 KeyboardEvent:
document.addEventListener(‘keyup’,function(e){console.log(e.keyCode)})
1、键盘对象中keycode属性可以得到相应键的ASCII码值
2、我们的keyup和keydown事件不区分字母大小写
3、我们的可以keypress事件区别字母大小写
element.focus(); js里面获得焦点的方法
注意:keydown和keypress文本框里面的特点:他们两个触发时马上就执行了里面的事件程序,这个时候文字还没来得及落入文本框中。
keyup事件触发时,文字已经落入文本框里面了