04.基本Dom操作

基础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>

​ 上边获取元素时,不管是NodeListHTMLCollection长得都很像数组,但是他们不是一个数组,是类数组,他们之前的区别这里暂时还讲不到。

​ 但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这种方法不会去动态的更新,而getElementsByClassNamegetElementsByTagName及时的更新了出来,从原来的获取到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>

​ 在这个例子中,classid都是有作用的,我们可以通过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]'

​ 只要给的不是个字符串,全都转成字符串!

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