网页是一棵树
JS如何操作这棵树
- 浏览器往window上加一个document即可
- document就是这个网页的整体
- JS把document作为对象进行操作
JS用document操作网页
- 这就是document Object Model文档对象模型
获取元素,也叫标签
- 有很多API
- window.idXXX或者直接idXXX (可以直接idXXX)
- document.getElementById('idxxx')
- 如果上面的id是全局变量,只能用这个
- 不要用
- document.getElementsByTagName('div')[ 下标(0,1,2,3)]
- 获取所有div标签,下标筛选定位某一个
- 不要用
- document.getElementsByClassName('red')[ 下标(0,1,2,3)]
- 获取所有类名为red的标签,下标筛选定位某一个
- 不要用
- document.querySelector('#idxxx')
- document.querySelectorAll('.red')[同理]
- 用哪一个
- 实际开发中,用querySelctor和querySelectorAll
- 做demo直接用idxxx,(可能导致沟通障碍,某些人不懂)
- 只有要兼容IE才会用getElement(s)ByXXX
小实操
- 找到某个标签
大于号可以省略,规则大部分参照css选择器功能,找到div里面第二个span标签,邮件reveal in elements panel 可以找打这个标签所在代码中的位置
- 找到所有标签
- 补充:以上两种代码后面可以加[],数组下标
获取特定元素
获取html标签document.documentElement
获取标签名竟然是大写
获取head元素
- document.head
获取body元素
- document.body
获取窗口元素(窗口不是元素)
window虽然不是标签,但是某些情况下用于获取到然后添加一些全局的事件监听
获取所有元素
-
document.all
- 特别之处: document.all最初是IE浏览器中的,但是其他浏览器为了区分,把这句话的值设置为falsy值(即为假值),如图IE浏览器中为真值,但是到其他浏览器中就是假值,通常用来检测是否需要兼容IE
- 但是 不影响这句话的使用
获取到的元素是什么?
- 获取的元素是对象 例:
- console.dir(div)看原型链
各层原型链
- 第一层原型 HTML.DivElement.prototype
- 这里面是所有div标签共有属性
- 第二层原型 HTMLElement.prototype
- 这里面是所有HTML标签共有的属性
- 第三层原型 Element.prototype
- 这里面是所有XML,HTML标签的共有属性,相对于HTML以上层级的一类
- 第四层原型 Node.prototype
- 这里面是所有节点共有的属性,节点包括XML标签文本注释、HTML标签文本注释等
- 第五层原型 EventTarget.prototype
- 里面最重要的属性是addEventListener
- 最后一层原型就是Object.prototype
div 完整原型链(自身属性和共有属性)
节点元素区别??
节点Node包括以下几种
MDN有完整描述,x.nodeType得到一个数字
- 1表示元素Element,也叫Tag
- 3表示文本Text
- 8表示注释Comment
- 9表示文档Document
- 11表示文档片段DocumentFrament
- 记住1和2即可
节点的增删改查
增
- 创建一个标签节点
- 创建一个文本节点
- 标签里面加文本
注意!!
- 插入页面中
创建的标签默认处于JS线程中年,必须把它插入到head或者body里面,才会生效 - 方法
document.body.appendChild(div)
或者:已经在页面中的元素.appendChild(div)
appendChild
- 页面中有div#test和div#test2
- let div=document.createElement('div')
- test1.appendChild(div)
- test2.appendChild(div) 结果 :最终在test2里面,一个元素不能在两个地方,除非复制一份,
- 方法:.cloneNode
- 官方文档参考developer.mozilla.org/zh-CN/docs/…
删
两种方法
- 旧方法: parentNode.Child(childNode)
- 新方法:childNode.remove()
注意:删除的内容还是保存在JS中,还可以再次调用
思考
如果node被移出页面(Dom)树,那么他还会再次回到页面中吗?
答:依然在内存中,还是可以再次调用的除非先移除,再赋值为null,断开与内存的连接
改属性
写标准属性
- 改class: div.className='red' 因为直接赋值会导致类名覆盖
- 如果之前的是blue会覆盖,如果不覆盖只能写成+='空格red'
- 改 class: div.classList.add('red') 不会覆盖
- 意思是在类名列表里面加一个red类名
- 改style:div.style='width:100px;height:100px;......'
- 改style一小部分:div.style.width='200px' -改data-*属性:div.dataset.x='frank'几乎很少用到
读标准属性
- div.class/div.id/a.href
- div.getAttibute('class')/a.getAttribute('href')
- 小区别
- a.href,当href为相对路径的时候,JS会将网页链接加在后面,造成错误
- 所以第二种方法获取的href更加准确,但是大部分情况下比如获取id,classname等,两种方法没有什么区别
改事件处理函数
div。onclick默认值为null
- 默认点击div不会有任何事情发生
- 但是如果把div.onclick改为一个函数fn
- 那么点击div的时候,浏览器就会调用这个函数
- 并且是这样调用的fn.call(div,event)
- div会被当做this
- event则包含了点击事件的所有信息,如坐标
改内容
改文本内容
- div.innerText='xxx'
- div.textContent='xxx'
- 两者没有任何区别
改HTML内容
- div.innerHTML='XXX ' 里面可以加一些标签,实现某些效果
改标签
- div.innerHTML='' //先清空
- div.appendChild(div2)//再加内容
改父级
- 找新父级
- newParent.appenedChild(div)
- 这样直接从原来的地方消失
查
查父级
- node.parentNode或者node.aprentElement
查父级的父级
- node.parentNode.parentNode
查子代
- node.childNodes或者node.children(推荐使用)
查同级
- node.parentNode.childNodes 还要排除自己,而且还要排除文本节点,更麻烦
- node.parentNode.children 还要排除自己
- 例:
引入一个空数组siblins,引入变量c2,先获得父级的所有元素,再获得父级的子集元素,循环法,排除自己
查
查看第一个
- node.firstChild
查看最后一个
- node.lastChild
查看上一个
- node.previousSibling
查看下一个
- node.nextSibling
遍历一个div里面所有的元素
travel=(node,fn)=>{
fn(node)
if(node.children){
for(let i=0;i<node.children.length;i++){
travel(node.children[i],fn)
}
}
}
travel(div1,(node)=>console.log(node))