Javascript DOM

DOM简介

文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过这些DOM接口可以改变网页的内容、结构和样式。

DOM树

文档:一个页面就是一个文档,DOM中使用document表示

元素:页面中所有的标签都是元素,DOM中使用element表示

节点:网页中所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

DOM把以上内容都看做对象

获取元素

getElementById(id)-根据ID获取

返回匹配到ID的DOM Element对象,若没有找到,返回null。id是大小写敏感的字符串。

<body>
    <div id="time">2022-2-2</div>
    <!-- 因为文档页面从上往下加载,所以先得有标签,所以script写在标签下面 -->
    <script>
        var timer=document.getElementById("time");
        console.log(timer);
        console.log(typeof timer);//object
         console.dir(timer);//打印我们返回的元素对象,更好地查看里面的属性和方法
    </script>
</body>

getElementsByTagName()-根据标签名获取

返回带有标签名的元素的集合,如果页面中没有这个元素,返回空的伪数组

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        //返回结果以伪数组形式存储
        //得到的元素对象是动态的
        var lis=document.getElementsByTagName("li");
        console.log(lis);
        console.log(lis[0]);
        //遍历依次打印元素对象
        for(let i=0;i<lis.length;i++)
        {
            console.log(lis[i]);
        }
    </script>
</body>

还可以获取某个元素(父元素)内部所有指定标签名的子元素。父元素必须是单个对象(必须指名是哪一个元素对象),获取的时候不包括父元素自己。

element.getElementsByTagName(‘标签名’);

<body>
    <ol id="olid">
        <li>1-1</li>
        <li>2-1</li>
        <li>3-1</li>
    </ol>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var ol=document.getElementsByTagName('ol');
        console.log(ol[0].getElementsByTagName('li'));

        //改进:通过给指定的ol标签赋予一个ID,来特指这一个元素对象
        var ol=document.getElementById('olid');
        console.log(ol.getElementsByTagName('li'));
    </script>
</body>

getElementsByClassName(‘类名’)-根据类名获取

返回元素对象集合

querySelector(‘选择器’)-根据指定选择器返回第一个元素对象

<body>
    <ol id="olid">
        <li class="li1">1-1</li>
        <li class="li1">2-1</li>
        <li class="li1">3-1</li>
    </ol>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var firstli=document.querySelector('.li1');
        console.log(firstli);
    </script>
</body>

qureySelectorAll(‘选择器’)-根据指定选择器返回

返回所有的

获取body标签

document.body

获取html标签

document.documentElement

事件基础

事件三要素

事件是可以被JavaScript侦测到的行为,简单解释:触发-响应机制。

事件由三部分组成:事件源、事件类型、事件处理程序。

事件源

事件源是事件被触发的对象,

事件类型

事件源是如何触发 什么事件

事件处理程序

通过一个函数赋值的方式完成

<body>
    <button id="btn">
        唐伯虎
    </button>
    <script>
        //获取事件源
        var btn=document.getElementById('btn');
        //绑定事件
        btn.onclick=function(){
            alert('点秋香');
        }
    </script>
</body>

操作元素

改变元素内容

element.innerText

从起始位置到终止位置的内容,但它不识别html标签,同时空格和换行也会去掉。

<body>
    <button>显示当前系统时间</button>
    <div>某个时间</div>
    <script>
        //当我们点击了按钮,div里面的文字会发生变化
        //1.获取元素
        let btn=document.querySelector('button');
        let div=document.querySelector('div');
        //2.注册事件
        btn.onclick=function(){
            div.innerText='2019-6-6';
        }
        
        //可以不注册事件
        let div=document.querySelector('div');
        div.innerText='2022-6-2';
    </script>
</body>

element.innerHTML

起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。

这两个属性都是可读写的,可以获取元素里面的内容,比如p.innerHTML

常用元素属性操作

<body>
    <button id="ZYL">朱一龙</button>
    <button id="ZLY">赵丽颖</button><br>
    <img src="material/ZLY.jpeg" alt="">
    <script>
        let zyl=document.getElementById('ZYL');
        let zly=document.getElementById('ZLY');
        let img=document.querySelector('img');

        zyl.onclick=function(){
            img.src="material/ZYL.jpeg" 
        }
        zly.onclick=function(){
            img.src="material/ZLY.jpeg"
        }
    </script>
</body>

其他属性以此类推。

表单元素属性操作

利用DOM可以操作以下表单元素的属性:type、value、checked、selected、disabled

<body>
    <button>按钮</button>
    <input type="text" value="输入内容">
    <script>
        let btn=document.querySelector('button');
        let input=document.querySelector('input');

        btn.onclick=function(){
            //表单里面的值 文字内容是通过value来修改的
            input.value='被点击';
            //表单被禁用,不能再点击 disabled
            //btn.disabled=true;
            //this指向的是事件函数的调用者
            this.disabled=true;
        }
    </script>
</body>

样式属性操作

1.element.style 行内样式操作

样式少,功能简单的情况下使用。

<body>
    <div></div>
    <script>
        var div=document.querySelector('div');
        div.onclick=function(){
            //style里面的属性采用驼峰命名法
            //JS修改style样式操作,产生的是行内样式,css权重更高,所以会覆盖掉原来的样式
            this.style.backgroundColor='blue';
            this.style.width=300;
        }
    </script>
</body>

2.element.className 类名样式操作

className会直接更改元素类名,原来的类名会被直接覆盖掉。

<body>
    <div></div>
    <script>
        var div=document.querySelector('div');
        div.onclick=function(){
            this.className='change'//类名改为change
        }
    </script>
</body>
div {
    width: 200px;
    height: 200px;
    background-color: pink;
}
.change{
    width: 300px;
    background-color: blue;
}

如果想保留原来的类名,可以this.className=‘first change’,在原先的类名后面加空格加上新的类名。

排他思想

当有多个按钮等元素需要绑定事件时。

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        var btns=document.querySelectorAll('button');
        for(var i=0;i<btns.length;i++)
        {
            btns[i].onclick=function()
            {
                //我们先把所有的按钮背景颜色去掉
                for(var i=0;i<btns.length;i++)
                {
                    btns[i].style.backgroundColor='';
                }
                //然后才让当前的背景颜色改变
                this.style.backgroundColor='pink';
            }
        }
    </script>
</body>

获取属性值

1.element.属性

2.element.getAttribute(‘属性’)

3.H5新增element.dataset.属性名 或者 element.dataset[‘属性名’](属性名不要data,其他的用驼峰命名法)

<body>
    <div data-index="2"> </div>
    <script>
        //dateset是一个集合,里面存放了所有以data开头的自定义属性
        console.log(div.dataset.index);
    </script>
</body>

区别是:第一种获取的是内置属性值(元素自带的属性);第二种和第三种主要获取自定义的属性。第三种只能获取data-开头的。

设置属性值

1.element.属性

2.element.setAttribute(‘属性’,‘属性值’);

区别同上。

移除属性

element.removeAttribute(‘属性’);

自定义属性

为了解决有些自定义属性容易引起歧义,很难判断时内置属性还是自定义属性,所以H5规定自定义属性data-开头作为属性名并且赋值。

节点操作

获取元素通常使用两种方法:利用DOM提供的方法获取元素、利用节点层次关系获取元素。

页面中所有内容都是节点,在DOM中,节点使用node来表示。

一般的,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。

  • 元素节点 nodeType 为1
  • 属性节点 nodeType为2
  • 文本节点nodeType为3 (包含文字、空格、换行)

节点层级

最常见的是父子兄层级关系。

父级节点

node.parentNode

<body>
    <div class="box">
        <div class="erweima"></div>
    </div>
    <script>
        //原来的获取元素
        let erweima=document.querySelector('.erweima');
        let box=document.querySelector('.box')

        //父节点,得到的是离元素最近的父级节点,找不到返回null
        let erweima=document.querySelector('.erweima');
        console.log( erweima.parentNode);
    </script>
</body>

子节点

1.parentNode.childNode

返回包含指定节点的子节点的集合(包含元素节点、文本节点等),该集合为即时更新的集合。

如果只想获得里面的元素节点,则需要专门处理

2.parentNode.children

是一个只读属性,返回所有的子元素节点,只返回元素节点,其余节点不返回。

3.parentNode.firstChild

返回第一个子节点,找不到返回null,也是包含所有的节点

4.parentNode.lastChild

返回最后一个子节点,同上。

5.parentNode.firstElementChild

返回第一个子元素节点。

6.parentNode.lastElementChild

返回最后一个子元素节点。

兄弟节点

1.node.nextSibling

返回当前元素的下一个兄弟节点,找不到则返回null,同样,也包含所有节点。

2.node.previousSibling

返回当前元素的上一个兄弟节点,找不到则返回null,同样,也包含所有节点。

3.node.nextElementSibling

返回当前元素的下一个兄弟元素节点

4.node.previousElementSibling

返回当前元素的上一个兄弟元素节点

创建节点

1.document.createElement(‘tagName’)

该方法创建由tagName指定的HTML元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建节点

2.innerHTML

添加节点

1.node.appendChild(child)

将一个节点添加到指定父节点的子节点列表末尾。node是父级,child是子级。

2.node.insertBefore(child,指定元素)

将一个节点添加到父节点的指定子节点前面。

想要页面有个新的元素,先创建,再添加。

<body>
    <input type="text">
    <button>发布</button>
    <ul></ul>
    <script>
        let btn=document.querySelector('button');
        let text=document.querySelector('input');
        let ul=document.querySelector('ul');

        btn.onclick=function()
        {
            let li=document.createElement('li');
            ul.appendChild(li);

            li.innerHTML=text.value + "<a href='#'>删除</a>";
        }
    </script>
</body>

删除节点

node.removeChild(child)

删除一个子节点,

复制节点

node.cloneNode()

返回调用该方法节点的一个副本。

克隆完要添加到想放的地方才行。

如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。括号为true,复制标签和里面的内容。

案例:动态生成表格

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>测试</title>
<link rel="stylesheet" href="css/Ceshi.css">
<script src="js/Ceshi.js"></script>
</head>
<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成绩</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
   
    <script>
        //1.先准备好学生的数据
        var datas=
        [
            {
                name:'魏璎珞',
                subject:'JavaScript',
                score:100
            },
            {
                name:'弘历',
                subject:'JavaScript',
                score:98

            },
            {
                name:'傅恒',
                subject:'JavaScript',
                score:99
            },
            {
                name:'明玉',
                subject:'JavaScript',
                score:88
            }
        ];

        //2.循环创建多个行(有多少个人就有多少行)
        var tbody=document.querySelector('tbody');
        for(var i=0;i<datas.length;i++)
        {
            var tr=document.createElement('tr');
            tbody.appendChild(tr);

            //行里面创建单元格(跟2数据有关系的),数量取决于取决于对象的属性个数
            for(var k in datas[i])
            {
                var td=document.createElement('td');
                //把对象里的属性值给td
                td.innerHTML=datas[i][k];
                tr.appendChild(td);
            }
            //3.创建有有删除两个字的单元格
            var td=document.createElement('td');
            td.innerHTML='<a href="javascript:;">删除</a>';
            tr.appendChild(td);
        }

        // 4.删除操作
        var as=document.querySelectorAll('a');
        for(var i=0;i<as.length;i++)
        {
            as[i].onclick=function()
            {
                //点击a,删除当前a所在行
                tbody.removeChild(this.parentNode.parentNode);
            }
        }
    </script>
</body>
</html>

CSS

table{
    width: 500px;
    margin: 100px auto;
    border-collapse: collapse;
    text-align: center;
}
td,th{
    border: 1px solid #333;
}
table thead tr{
    height: 40px;
    background-color: #ccc;
}

事件高级

注册事件

给元素添加事件,称为注册事件或绑定事件。注册事件有两种方式:传统方式和方法监听注册方式。

传统注册方式

  • 利用on开头的事件
  • 特点:注册事件唯一性
  • 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数

方法监听注册方式

  • addEventListener()它是一个方法
  • 特点:同一个元素同一个事件可以注册多个监听器
  • 按注册顺序依次执行

eventTarget.addEventListener(type,listener[,useCapture])

该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。

  • type:事件类型字符串,比如click、mouseover,注意这里不需要带on。记得带引号
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认false,处于冒泡阶段,true时处于捕获阶段。
<body>
    <button>监听</button>
    <script>
     var btn=document.querySelector('button');
     btn.addEventListener('click',function(){
        alert(22);
     })
     btn.addEventListener('click',function(){
        alert(33);
     })
    </script>
</body>

删除事件

传统注册方式

eventTarget.on事件=null;

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs=document.querySelectorAll('div');
        divs[0].οnclick=function()
        {
            alert(11);
            divs[0].οnclick=null;
        }
    </script>
</body>

方法监听注册方式

eventTarget.removeEventListener(type,listener[,useCapture])

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs=document.querySelectorAll('div');
        divs[0].addEventListener('click',fn)//里面的fn 不需要加小括号调用
        function fn(){
            alert(22);
            divs[0].removeEventListener('click',fn)
        }
    </script>
</body>

DOM事件流

事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

DOM事件流分为3个阶段:捕获阶段、当前目标阶段、冒泡阶段。

事件冒泡;事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程。有些事件是没有冒泡的,比如onblur,onfocus,onmouseenter,onmouseleave

事件捕获:由DOM最顶层节点开始,任何逐级向下传播到最具体的元素接收的过程。

事件对象

写到我们侦听函数的小括号里面,当形参来看。事件对象只有有了事件才会存在。它是系统给我们自动创建的,不需要我们传递参数。事件对象是我们事件的一系列相关数据的集合,和事件相关的,比如鼠标点击里面就包含了鼠标相关信息。

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs=document.querySelectorAll('div');
        //事件对象可以自己命名
        divs[0].onclick=function(event){
            console.log(event);
        }

        divs[1].addEventListener('click',function(event)
        {
            console.log(event);
        })
    </script>
</body>

e.target

返回触发事件的对象

<body>
    <ul>
        <li></li>
    </ul>
    <script>
        var ul=document.querySelector('ul');
        ul.addEventListener('click',function(e){
            //e.target返回的是触发事件的元素
            console.log(e.target);//<li></li>
            //this返回的是绑定事件的元素
            console.log(this);//<ul><li></li></ul>
        })
    </script>
</body>

e.type

返回事件的类型,比如click,mouseover等,不带on

e.preventDefault()

阻止默认行为(事件),比如让链接不跳转,提交按钮不提交。dpm标准写法。

此外还有(仅限于传统注册方式):

  • e.returnValue
  • retun false

e.stopPropagation()

阻止冒泡。事件冒泡本身的特性,会带来好处和一定的坏处。应用:在孩子处做了点击后就停止冒泡了,不再往上传播

事件委托

事件冒泡也会带来好处。

场景:点击每个li都会弹出对话框,以前需要给每个li注册事件,非常辛苦,而且访问DOM的次数越多,这就会延长整个页面的交互就绪时间。

事件委托也称事件代理,在JQury里面称为事件委派。

事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在父节点上,然后利用冒泡原理影响设置每个子节点。

<body>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
        var ul=document.querySelector('ul');
        ul.addEventListener('click',function(e){
            e.target.style.backgroundColor='blue';
        })
    </script>
</body>

常用鼠标事件

onclick

鼠标点击左键触发

onmouseover

鼠标经过触发。经过自身盒子会触发,经过子盒子还会触发。

mouseenter

鼠标经过触发,只经过自身盒子会触发。mouseenter不会冒泡。

onmouseout

鼠标离开触发

mouseleave

鼠标离开触发,不会冒泡。

onfocus

获得鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmouseup

鼠标弹起触发

onmousedown

鼠标按下触发

contextmenu

主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单。

禁止鼠标右键菜单:

<body>
    我是一段不愿意分享的文字
    <script>
        document.addEventListener('contextmenu',function(e){
            e.preventDefault();
        })
    </script>
</body>

selectstart

禁止鼠标选中

<body>
    我是一段不愿意分享的文字
    <script>
        document.addEventListener('selectstart',function(e){
            e.preventDefault();
        })
    </script>
</body>

鼠标事件对象

e.clientX/e.clientY

返回鼠标相对于浏览器窗口可视区的X/Y坐标。

e.pageX/e.pageY

返回鼠标相对于文档页面的X/Y坐标。

当有滚动条时,滑动滚动条相同地方坐标会不同

e.screenX/e.screenY

返回鼠标相对于电脑屏幕的X/Y坐标。

案例:鼠标跟随

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>测试</title>
<link rel="stylesheet" href="css/Ceshi.css">
<script src="js/Ceshi.js"></script>
<style>
    img{
        position: absolute;
    }
</style>
</head>
<body>
    <img src="material/zylmouse.jpeg" alt="">
    <script>
        var pic=document.querySelector('img');
        document.addEventListener('mousemove',function(e){
            //得到鼠标坐标
            var x=e.pageX;
            var y=e.pageY;
            //把坐标给图片,记得加单位,减去图片尺寸的一半可以让鼠标在图片中间
            pic.style.left=x-100+'px';
            pic.style.top=y-100+'px';
        })
    </script>
</body>
</html>

常用键盘事件

onkeyup

某个键盘按键被松开时触发

    <script>
        document.addEventListener('keyup',function(){
            console.log(松手);
        })
    </script>

onkeydowm

某个按键被按下时触发

onkeypress

某个按键被按下时触发,但是它不识别功能键,比如ctrl,shift,箭头等

三个事件执行顺序:keydowm->keypress->keyup

keyCode

键盘事件中的keyCode属性可以得到相应键的ASCII码值。已经淘汰了,用e.key

    <script>
        document.addEventListener('keyup',function(e){
            console.log(e.keyCode);
        })
    </script>

注意:

  • 我们的keyup和keydown事件不区分字母大小写
  • keypress事件区分字母大小写
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值