基础DOM
DOM的全称是Document Object Model -> 文档对象模型,我们可以使用JavaScript来操作DOM,从而改变改变文档的结构,样式和内容(即网页显示的内容和样式)。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。也就是说DOM就是一个对象,这个对象叫做document。
因此我们可以在网页里打印出整个文档:
console.log( document )//得到一个对象,点开这个对象就可以看到整个文档的结构和内容
//document是js自带的,所以不会报错
既然可以在document
里打印出文档的结构,我们就可以获取并修改。
获取元素
修改的第一步是获取,先得到,再修改。
获取元素又这样的几个函数:
- document.querySelector('完整css选择器')
query是查询的意思,Selector是选择器的意思,连起来翻译为:查询选择器,document是一个对象,它下边有一个querySelector属性,是一个函数,我们把css选择器(字符串)作为参数传递进去,会返回第一个复合条件的元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="item list one">123</div>
<div></div>
<div></div>
<div></div>
</body>
<script>
var div = document.querySelector('div')
console.log( div )//<div class="item list one">123</div>
</script>
</html>
上例中我们传入的选择器是div
,在css里如果用div
选择,代表选中所有的div
标签,而这里querySelector
这个方法,只能返回到匹配的第一项:
<body>
<div></div><!-- 新加了一个div -->
<div class="item list one">123</div>
<div></div>
<div></div>
<div></div>
</body>
<script>
var div = document.querySelector('div')
console.log( div )//<div></div>
</script>
</html>
上图中我们改变了结构之后,返回的内容变了,变成了第一个没有内容的div
。
-
document.querySelectorAll('完整css选择器')
html
结构不变,和上边的一样。var divList = document.querySelectorAll('div') console.log(divList)//NodeList(4) [div.item.list.one, div, div, div] //通过指定下标,可以获取到里边的某一个元素 console.log( divList[0] )//<div class="item list one">123</div>
获取到了页面中所有的div。
-
document.getElementById('Id名')
只得到找到的第一个
<body> <div id="box"></div> ... </body> <script> var div = document.getElementById('box') console.log( div )//<div id="box"></div> </script>
document.getElementsByClassName('class名')
得到
<body>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</body>
<script>
var div = document.getElementsByClassName('item')
console.log( div )//HTMLCollection(4) [div.item.list.one, div.item, div.item, div.item]
</script>
获取到了所有类名里有item
的元素。
- document.getElementsByTagName('标签名')
<body>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</body>
<script>
var div = document.getElementsByClassName('div')
console.log( div )//HTMLCollection(4) [div.item.list.one, div.item, div.item, div.item]
</script>
- document.getElementsByName('name名称')
通过元素的name属性来返回找到的一组元素。
<body>
<input name="myInput" type="text" size="20" />
<input name="myInput" type="text" size="20" />
<input name="myInput" type="text" size="20" />
</body>
<script>
var div = document.getElementsByName('myInput')
console.log( div )//NodeList(3) [input, input, input]
</script>
上边获取元素时,不管是NodeList
和HTMLCollection
长得都很像数组,但是他们不是一个数组,是类数组,他们之前的区别这里暂时还讲不到。
但js里不是所有的元素都是需要先获取再使用的,如下几个就可以直接拿来用:
document.title //文档的标题,也就是title标签里的内容
document.body //body元素
document.head // head标签
document.documentElement // html标签
现在我们有6中方法来获取元素他们之间有什么区别呢?
这些获取元素的方法分为两类:静态方法和动态方法,接下来我们看看他们之间的区别。
要观察静态方法和动态方法的区别我们需要先介绍一下innerHTML
:
<body>
<div class="item">
<p>
123
</p>
</div>
</body>
<script>
var div = document.querySelector('.item')
console.log( div )//<div class="item"></div>
console.log( div.innerHTML )//<p>123</p>
//获取一个元素后通过.innerHTML可以获取到里边所有的元素和元素里的内容,同时也可以进行修改
div.innerHTML += '<div>456</div>'
console.log( div.innerHTML )//<p>123</p>'<div>456</div>'
</script>
接下来我们看看静态和动态方法比较:
<body>
<div class="item"></div>
</body>
<script>
var divOne = document.querySelectorAll('.item'),
divTwo = document.getElementsByClassName('item'),
divThree = document.getElementsByTagName('div')
console.log( divOne )//NodeList [div.item]
console.log( divTwo )//HTMLCollection [div.item]
console.log( divThree )//HTMLCollection [div.item]
document.body.innerHTML += '<div class="item"></div>'
console.log( divOne )//NodeList [div.item]
console.log( divTwo )//HTMLCollection(2) [div.item, div.item]
console.log( divThree )//HTMLCollection(2) [div.item, div.item]
</script>
从上例中我们发现,在动态的给html
文档中添加元素的时候,document.querySelectorAll
这种方法不会去动态的更新,而getElementsByClassName
和getElementsByTagName
及时的更新了出来,从原来的获取到1个变成获取到了两个。
静态方法有:
document.querySelector()
document.querySelectorAll()
动态方法有:
document.getElementById()
document.getElementsByClassName()
document.getElementsByTagName()
document.getElementsByName()
改变元素的类名:
我们获取到一个元素之后,可以通过
.className
来获取到这个元素的类名,然后对其修改。
<body>
<div class="item one"></div>
</body>
<script>
var div = document.querySelector('.item')
console.log( div.className )//"item one"
div.className += ' two'//此时我们看到元素的类名里多加了一个two
</script>
除此之外还有另外一个查看元素类名的方法:
<font color="red"><b>classList</b></font>
classList返回一个元素的类名属性类数组。
<body>
<div class="item one"></div>
</body>
<script>
var item = document.querySelector('.item')
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
console.log( item[0] )//'item'
console.log( item[1] )//'one'
</script>
classList
下有如下几个方法给我们用来操作某个元素的类名:
add()
//html和上边的一样
item.classList.add('three')
console.log( item.classList )//DOMTokenList(3) ["item", "one", "three", value: "item one three"]
上边我们只添加了一个,如果想添加多个,多穿几个参数用逗号隔开就可以了:
item.classList.add('three', 'four')
console.log( item.classList )//DOMTokenList(4) ["item", "one", "three", "four", value: "item one three four"]
remove()
除了添加外我们还可以删除:
console.log( item.classList )//DOMTokenList(4) ["item", "one", "three", "four", value: "item one three four"]
item.classList.remove('four')
console.log( item.classList )//DOMTokenList(3) ["item", "one", "three", value: "item one three"]
同样的我们也可以删除多个,参数之间用逗号隔开:
console.log( item.classList )//DOMTokenList(4) ["item", "one", "three", "four", value: "item one three four"]
item.classList.remove('three','four')
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
replace( oldClass, newClass )
用一个新类名替换已有的类名。replace翻译为替换。
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
item.classList.replace('one', 'some')
console.log( item.classList )//DOMTokenList(2) ["item", "some", value: "item some"]
toggle()
有就删除,没有就添加。toggle也叫做开关。
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
item.classList.toggle('one')
console.log( item.classList )//DOMTokenList(1) ["item", value: "item"]
item.classList.toggle('one')
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
contains()
console.log( item.classList )//DOMTokenList(2) ["item", "one", value: "item one"]
console.log( item.classList.contains('one') )//true
console.log( item.classList.contains('two') )//false
元素的属性不止有class
还有id
和其他属性,DOM
为我们提供了几个可以获取,查找和设置元素属性的函数:
setAttribute('属性名','属性值') 设置属性
getAttribute('属性名') 获取属性
removeAttribute('属性名') 删除属性
他们会把结果返回回来,也就是说我们可以直接打印,或者拿一个变量接收。
<body>
<div id="box" class="item one"></div>
</body>
<script>
//这个几个函数都是用在元素身上的,因此需要先获取到元素。
//假设下边的删除,获得和修改例子都是独立的,不会相互影响。实际上去这样写的时候上一步的结果会影响下一步,具体的可以在代码中尝试
var box = document.getElementById('box')
console.log(box)//<div id="box" class="item one"></div>
//获得
console.log( box.getAttribute('class') )//item one
//和直接点className没有区别
console.log( box.ClassName )//item one
//id和直接点id没有区别
console.log( box.getAttribute('id') )//box
console.log( box.id )//box
//删除
console.log( box.removeAttribute('class') )
console.log( box )//<div id="box"></div> class属性被删除了
//删除的时候会有一点不同
box.className = ''//等号是赋值,可以把class属性清空但是class属性还是会显示在元素上
console.log( box )//<div id="box" class></div>
//设置
box.setAttribute('title', 'helloworld')//给这个div设置了一个title属性,值为title
console.log( box )//<div id="box" class="item one" title="helloworld"></div>
//直接点title
box.title = 'helloworld'
console.log( box )//<div id="box" class="item one" title="helloworld"></div>
</script>
上边我们给元素设置、查找或者删除属性的时候都是元素的自有属性,也就是说元素身上本来就可以有这些属性,但除此之外在开发中我们会经常为元素设置一些自定义属性:
所谓自定义属性就是元素本身没有这个属性,但是我们可以自己创造属性名。
例如:
<body>
<div class="box" id="item" abc='hello'></div>
</body>
在这个例子中,class
和id
都是有作用的,我们可以通过css
来给.box
或者#item
设置样式,我们也可以通过getElementsById
或者getElementsByClassName
来获取到这些元素,貌似abc
就显得毫无意义,但通过以后的学习我们会发现自定义属性其实有大用处。
既然它也是有用的,那么我们除了直接把自定义属性写在标签里外,可以用js
动态的获取,设置和删除吗?当然可以:
依然是使用:
setAttribute('属性名','属性值') 设置属性
getAttribute('属性名') 获取属性
removeAttribute('属性名') 删除属性
注意,如果修改自定义属性,非常建议使用这三个函数:
<body>
<div id="box" class="item one"></div>
</body>
<script>
var box = document.getElementById('box')
console.log( box )//<div id="box" class="item one"></div>
//使用点来添加,修改,清空自定义属性
box.abc = 'hello'
console.log( box )//<div id="box" class="item one"></div> 我们发现,abc属性好像并没有被设置上
console.log( box.abc )//'hello'确实可以打印出来
//如果使用set来设置
box.setAttribute('abc', 'hello')
console.log( box )//<div id="box" class="item one" abc='hello'></div> 这一次我们直接可以在打印box的时候看到他身上有一个abc属性
//修改没有什么不同,都可以修改
//删除,和类名一样,通过box.abc=''只能清空,不能删除掉abc这个属性,而removeAttribute可以
</script>
本节左后一个知识点:
innerText
<body>
<div class="item one">
<p>
123
</p>
<span>
456
</span>
</div>
</body>
<script>
var item = document.querySelector('item')
console.log( item )//把整个item都打印了下来
console.log( item.innerHTML )//<p>123</p><span>456</span>
</script>
除此之外我们还有innerText
来打印文本:
console.log(item.innerText)//'1 2 3' 只能打印出item元素里的所有文本,不管这些内容属于哪个子元素
//当然了获取的目的是为了操作,我们也可以对其进行操作
item.innerText = 'hello'
console.log(item.innerText)//<div class="item one"></div> 毁天灭地,把老子的p和span标签都给干没了,就是这么硬核
因此我们在使用innerText
的时候,如果只想改变某个元素里的文本内容,就要准确的指明这个元素:
var p = document.querySelector('.item > p')
console.log( p )//<p>123</p>
p.innerText = 'hello'
console.log( p )//<p>hello</p>
他和innerHTML
的区别:
item.innerHTML = '<div><p>123</p></div>'
console.log( item )//<div class="item one"><div><p>123</p></div></div>
//innerHTML认得标签
item.innerText = '<p>123</p>'
//页面中class为item one的这个div里边的内容直接变成<p>123</p>,p标签没有被转义,可以手动在页面中尝试
innerText
吃什么吐什么,innerHTML
认得标签。
非常完美,但是刚才我们给的都是字符串,假如给其他类型呢?
//Number
p.innerText = 123
console.log(p.innerText)//'123'
//布尔值
p.innerText = true
console.log(p.innerText)//'true'
p.innerText = false
console.log(p.innerText)//'false'
//undefined和null
p.innerText = undefined
console.log(p.innerText)//'undefined'
p.innerText = null
console.log(p.innerText)//'null'
//[]
p.innerText = []
console.log(p.innerText)//''
p.innerText = [1, 2, 3]
console.log(p.innerText)//'1, 2, 3'
//{}
p.innerText = {}
console.log(p.innerText)//'[object Object]'
p.innerText = {a: 1, b: 2}
console.log(p.innerText)//'[object Object]'
只要给的不是个字符串,全都转成字符串!