JavaScript DOM 篇

DOM Document Object Model(文档对象模型)

如何获取页面元素

1.根据ID获取

getElementById(ID);

<body>
   <div id="card">
       黎明的那道光
   </div>
   <script>
       document.getElementById(card);
   </script>
</body>

console.dir()打印我们返回的元素对象,更好的查看里面的属性和方法

2.根据标签名获取

使用document.getElementsByTagName()可以返回带有指定标签名的集合

 <ul>
        <li>有一种悲伤</li>
        <li>北方的冬夜是否暖过上海的夏天</li>
        <li>不找了</li>
        <li>世间美好与你环环相扣</li>
    </ul>
    <script>
        //获取的是元素对象的集合,以伪数组的形式存储
        var lis=document.getElementsByTagName('li');
        console.log(lis);
     console.log(lis[0]);//获取第一个li
</script>

还可以获取某个元素(父元素)内部所有指定标签名的子元素

element.getElementsByTagName('标签名');

3.通过HTML5新增的方法获取

document.getElementsByClassName('类名')//根据类名返回元素对象集合

querySelector()返回指定选择器的第一个元素对象,注意里面的选择器需要加符号
querySelectorAll()返回指定选择器的所有元素对象

<div class="box">123</div>
   <div class="box">456</div>
   <script>
       var boxs=document.getElementsByClassName('box');
       console.log(boxs);
       //2.querySelector()返回指定选择器的第一个元素对象,注意里面的选择器需要加符号
       //3.querySelectorAll()返回指定选择器的所有元素对象
       var num=document.querySelector('.box');
       console.log(num);
   </script>

 

4.特殊元素获取(body 或html标签)

 获取body  document.body;

获取html   document.documentElement;

5.利用节点的层级关系获取元素

事件三要素:

事件源,事件类型,事件处理程序

 <button id="btn">唐伯虎</button>
   <script>
       //实现点击按钮弹出对话框
       //1.事件源 事件被触发的对象 在此处为按钮
       var btn=document.getElementById('btn');
       //2.事件类型 如何触发这个时间 是鼠标点击 还是鼠标经过等等
       btn.onclick=function(){//实现了鼠标点击时弹出对话框点秋香
           alert('点秋香');
       }
   </script>

执行事件的步骤

1.获取事件源

2.注册事件(绑定事件)

3.添加事件处理程序(采取函数赋值程序)

 

 js的DOM操作可以修改网页结构的内容,结构和样式,可以利用DOM操作元素来修改元素里面的内容,属性等

改变元素内容:

element.innerText 从起始位置到终止位置的内容,但他去除html的标签。同时空格和换行也会去掉

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

<body>
  <button>显示当前系统时间</button>
  <div>时间</div>
  <script>
      //实现点击按钮div里的文字变成当前时间
      //1.获取元素
      var btn=document.querySelector('button');
      var div=document.querySelector('div');
      //2.注册事件
      btn.onclick= function() {
          div.innerText=getDate();//若这句不在函数内,则刷新之后直接出时间,不用点击按钮
      }
      function getDate() {
          var date=new Date();
          var year=date.getFullYear();
          var month=date.getMonth()+1;
          var dates=date.getDate();
          var day=date.getDay();
          var arr=['星期日','星期一','星期二','星期三','星期三','星期四','星期五','星期六'];
          return '今天是'+year+''+month+''+dates+''+arr[day];
      }
  </script>
</body>

innerText (非标准)与innerHTML(w3c标准,更为常用)的区别

①前者不识别html的标签,后者识别

 <div></div>
  <script>
      var div=document.querySelector('div');
      div.innerText='<strong>今天是:</strong>2019';//输出为<strong>今天是:</strong>2019
      div.innerHTML='<strong>今天是:</strong>2019';//按理想效果输出
  </script>

②这两个属性都是可读写的,可以获取标签里面的内容

 <p>
      我是文字
      <span>345</span>
  </p>
  <script>
      var p=document.querySelector('p');
      console.log(p.innerText);//我是文字 345
      console.log(p.innerHTML);/*我是文字
                                 <span>345</span>*/
  </script>

修改元素属性

 案例(实现点击不同按钮时显示不同的图片)

<button id="tp1">图片1</button>
    <button id="tp2">图片2</button>
    <img src="images/图片1.jpg" title="图片1">
    <script>
        var tp1=document.getElementById('tp1');
        var tp2=document.getElementById('tp2');
        var img=document.querySelector('img');
        tp1.onclick=function(){
            img.src='images/图片1.jpg';
            img.title='图片1';
        }
        tp2.onclick=function(){
            img.src='images/图片2.jpg';
            img.title='图片2';
        }
    </script>

案例(实现不同时间显示不同图片和文字)

<img src="images/图片1.jpg">
    <div>上午</div>
    <script>
        //实现不同时间显示不同的图片和文字
        var img=document.querySelector('img');
        var div=document.querySelector('div');
        var date=new Date();
        var hour=date.getHours();
        if(hour>12){
            img.src='images/图片2.jpg';
            div.innerHTML='下午';
        }
        else{
            img.src='images/图片1.jpg';
            div.innerHTML='上午';
        }
    </script>

表单元素的属性操作(.innerHTML可以对普通盒子如div里的内容进行修改,但对表单里的内容则不能用.innerHTML)

利用DOM可以操作如下表单的属性

type,value,checked,selected,disabled

<button>按钮</button>
   <input type="text" value="输入内容">
   <script>
       var btd=document.querySelector('button');
       var input=document.querySelector('input');
       btd.onclick=function(){
           input.value='被点击了';
           btd.disabled=true;//实现点击按钮后按钮被禁用
      //或者this.disabled=true;this指向的是事件函数的调用者
} </script>

案例(仿京东显示密码,点击按钮将密码框切换为文本框,并可以查看密码明文)

<style>
       .box{
           position:relative;
           width:400px;
           border-bottom:solid #ccc 1px;
           margin:100px auto;
       }
       .box input{
           width:370px;
           height:30px;
           border:0;
           outline: none;/*不会的地方*/
       }
       .box img{
           width:24px;
           position:absolute;
           right: 10px;
           bottom:5px;

       }
   </style>
</head>
<body>
   <div class="box">
       <label for="">
           <img src="images/图片1.jpg" id="eye">
       </label>
       <input type="password" name="" id="pwd">
   </div>
   <script>
       var eye=document.getElementById('eye');
       var pwd=document.getElementById('pwd');
       var flag=0;
       eye.onclick=function(){
           if(flag==0){
            pwd.type='text';
            eye.src='images/图片2.jpg';
            flag=1;
           }
           else{
               pwd.type='password';
               eye.src='images/图片1.jpg';
               flag=0;
           }
       }
   </script>

样式属性操作

通过js来修改元素的大小,颜色,位置等样式。

element.style (里面的属性采取驼峰命名法)行内样式操作

//js修改style样式操作,产生的是行内样式,css权重比较高

element.className  类名样式操作

循环精灵图

①首先精灵图图片排列是有规律的

②核心思路:利用for循环,修改精灵图片的背景位置background-position

显示隐藏文本框内容

//鼠标点击时文本框默认内容消失,未点击则继续显示

 首先表单需要两个新的事物 获得焦点onfocus 失去焦点onblur

<body>
    <input type="text" value="手机">
    <script>
        var text=document.querySelector('input');
        text.onfocus = function() {
            if(text.value==='手机'){
                text.value= '';
            }
            text.style.color='#333';
        }
        text.onblur = function() {
            if(text.value=== ''){
                text.value='手机';
            }
            text.style.color='#999';
        }
    </script>
</body>

使用className修改样式属性

具体操作是先在style中写一个类的样式,然后当对目标进行某项操作想要实现这个样式时,可用classNane使得目标具有这个类样式所设定的属性,适合于功能较多或者样式复杂的情况,注意className会更改元素的类名,覆盖原来的类名

如果想要保留原来的类名。、,假设原来的类名是first,则只需代码中//位置修改为this.className='first chance'

<style>
       div{
           background-color: pink;
           width:200px;
           height:200px;
       }
       .chance{
           background-color: purple;
           color:white;
           font-size: 15px;
       }
    </style> 
</head>
<body>
    <div>文本</div>
    <script>
        var text=document.querySelector('div');
        text.onclick= function() {
            this.className='chance';//
        }
    </script>
</body>

排他思想

先设置其他元素的样式,才来设置自己的

如果有同一组元素,希望进行某种操作时其中的一个有某种样式,其余的无,则可以运用排他思想,主要通过对伪数组进行for循环

比如样例(多个按钮实现被点击按钮变成粉红色)

 <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <script>
        var btn=document.getElementsByTagName('button');
        for(var i=0;i<btn.length;i++){
        btn[i].onclick=function() {
            for(var i=0;i<btn.length;i++){
                btn[i].style.backgroundColor= '';
            }
            this.style.backgroundColor= 'pink';
        }
    }
    </script>

自定义属性

自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面而不用保存到数据库中

有些自定义属性容易引起歧义,不好分辨是自定义属性还是内置属性,这一问题再H5中得以解决。H5规定自定义属性以data-开头并且赋值

如果自定义属性里面有多个用-链接的单词,我们获取时采取驼峰命名法比如自定义属性data-list-name=" ",获取时为element.dataset.listName

 获取属性值

1.element.属性(获取内置属性,元素自带的属性如id,class之类)

2.elememt.Attribute(‘属性')(主要获取自定义属性,程序员自己定义的属性)已有的属性值可能无法满足需求,这时可自定义属性

3.element.dataset.属性(此时属性里不用含data-)或者element.dataset['属性'](此时属性里不用含data-) H5新增获取自定义属性值的方法  ie11

设置元素属性值

element.属性='值',修改class的属性值时,是element.className='值'。(设置内置属性值)

element.setAttribute('属性','值')(主要针对自定义属性)

移除属性

element.removeAttribute('属性');

节点

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

HTML DOM树中的所有节点都可以通过JavaScript进行访问,所有HTML元素(节点)都可以被修改,也可以创建或删除。一般的,节点要至少拥有nodeType(节点类型),nodeName(节点名称),nodeValue(节点值),

元素节点 nodeType 为1

属性节点 nodeType 为2

文本节点 nodeType 为3(文本节点包括文字 空格 换行等)

实际开发中,节点操作主要是元素节点

1.父节点node.parentNode.如果指定的节点没有父节点则返回NULL

2.子节点parentNode.childNodes(得到所有的子节点,包括元素节点,文本节点等等)如果只想获得里面的元素节点,可以通过for循环来判断,如果其nodeType为1则是元素节点,然后进行操作

parentNode.children(非标准)返回所有的子元素节点,虽然是非标准,但得到了各个浏览器的支持,可以放心使用。

3.节点操作中第一个子元素和最后一个子元素

parentNode.firstChild获取的是第一个子节点,包括文本节点

parentNode.lastChild获取最后一个子节点,同样包括文本节点

parentNode.firstElementChild获取第一个子元素节点

parentNode.lastElementChild获取最后一个子元素节点//这两个有兼容问题。IE9及以上才可以使用

实际开发中常用的是用伪数组来获取

paerentNode.children[数组索引]。

4.兄弟节点

node.nextSibling获取下一个节点,包含元素节点和文本节点。

node.previousSibling获取上一个节点,包含元素节点和文本节点

想要通过兄弟节点只获得元素节点

node.nextElementSibling

node.previousElementSibling//这两个也是有兼容性问题IE9及以上

可以自己封装一个兼容性的函数

 

 

 5.节点操作之创建和添加节点

想要页面中添加一个元素,有两步,先要创建元素,然后再添加元素。

document.creatElement('tagName');

这个元素原本是不存在的,是根据我们的需求动态生成的,所以又称为动态创建元素节点

只创建节点是不够的,还需要与添加节点同时使用,告诉计算机将节点添加到哪里

添加节点

node.appendChild(child),此方法将一个节点添加到指定父节点的子节点列表末尾,类似于css里面的after伪元素。

//实现向ul里面添加li
<ul></ul>
  <script>
      var li =document.createElement('li');
      var ul =document.querySelector('ul');
      ul.appendChild(li);
  </script>

node.insertBefore(child,指定元素)将一个节点添加到指定子节点的前面,类似于css里面的before伪元素

<ul>
      <li>123</li>
  </ul>
  <script>
      var lili =document.createElement('li');
      var ul =document.querySelector('ul');
      ul.insertBefore(lili,ul.children[0]);
  </script>

 简单版发布留言的案例

核心思路:点击发布之后,动态创建一个li,添加到ul里面,

创建li的同时,将文本域里面的值通过li.innerHTML赋值给li

如果需要新的留言在后面显示,使用appendChild如果希望在前面显示,使用innsertBefore

 <textarea name="" id="" cols="30" rows="10"></textarea>
    <button>发布</button>
    <ul>
    </ul>
    <scriPt>
        var text=document.querySelector('textarea');
        var btn=document.querySelector('button');
        var ul=document.querySelector('ul');
        btn.onclick = function() {
            if(text.value==''){
                alert('您没有输入内容');
                return false;
            }
            else{
                var li=document.createElement('li');
                li.innerHTML=text.value;
                ul.appendChild(li);
            }
        }
    </scriPt>

删除节点

node.removeChild(child)

删除一个节点的例子

<body>
   <ul>
       <li>熊大</li>
       <li>熊二</li>
       <li>光头强</li>
   </ul>
   <script>
       var ul=document.querySelector('ul');
       ul.removeChild(ul.children[0]);
   </script>
</body>

点击一次按钮删除一个节点的例子

点击一次按钮删除一个节点,当无节点时,按钮变为禁用按钮

 <button>删除</button>
   <ul>
       <li>熊大</li>
       <li>熊二</li>
       <li>光头强</li>
   </ul>
   <script>
       var ul=document.querySelector('ul');
       var btn=document.querySelector('button');
       btn.onclick=function() {
           if(ul.children.length==0){
               this.disabled='true';
           }
           else
           ul.removeChild(ul.children[0]);
       }
   </script>

 复制节点

node.cloneNode()返回调用该函数节点的一个副本,也成为复制节点或拷贝节点。

如果括号里参数为空或者false,则为浅拷贝,只克隆复制节点本身,不克隆里面的子节点

node.cloneNode(true)深拷贝

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul=document.querySelector('ul');
        var lili=ul.children[0].cloneNode(true);
        ul.appendChild(lili);
    </script>
</body>

 三种动态创建元素的区别

document.write()(不常用,了解即可)直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面全部重绘。

element.innerHTML.创建多个元素效率更高(不要用拼接字符串,采取数组形式拼接),结构稍微复杂

createElement()创建多个元素效率稍微低一点点,但是结构更清晰

事件高级

注册事件的两种方式

1.传统方式(前面一直用的方式)

①利用on开头的事件onclick

②注册事件的唯一性

同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面的处理函数

为了解决此问题,下面的注册方式应运而生

2.方法监听注册方式

①addEventListener()它是一个方法,IE9以前的版本不支持,可使用attachEvent()(非标准,不常用)注册事件

②同一个元素同一个事件可以添加多个监听器

③按注册顺序依次执行

④如何使用

eventTarget.addEventListener(type,Listener[,userCapture]);

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

type :事件类型字符串,如click,mouseover,注意这里不带on

listener : 事件处理函数,事件发生时,会调用该监听函数

useCapture : 可选参数,是一个布尔值,默认是false

实现点击按钮弹出内容

<body>
    <button>按钮</button>
    <script>
        var btn=document.querySelector('button');
        //addEventListener里面的事件类型是字符串,而且不带on
        btn.addEventListener('click',function() {
            alert('hi');
        })
        btn.addEventListener('click',function() {
            alert('hello');
        })
        //会先弹出hi,然后弹出hello
    </script>
</body>

封装函数解决兼容性问题

 

 删除事件(解绑事件)

1.传统注册方式

eventTarget.onclick=null;

2.方法监听注册方式

eventTarget.removeEventListener(type,Listener[,userCapture]);

 
 <div>12</div>
    <div>22</div>
    <script>
        //普通点击得删除事件
        var divs=document.querySelectorAll('div');
        divs[0].onclick=function() {
            alert('33');
            divs[0].onclick=null;
        }
        divs[1].addEventListener('click',fn);
        //因为删除时间需要知道函数名,所以此处不再用匿名函数
        function fn() {
            alert('22');
            divs[1].removeEventListener('click',fn);
        }
    </script>

DOM事件流

事件流描述的是从页面中接受事件的顺序

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

DOM事件流分为三个阶段

1,捕获阶段

2.当前目标阶段

3.冒泡阶段

 

 JS只能执行捕获或者冒泡的其中一个阶段

onclick 和 attackEvent 只能得到冒泡阶段

addEventListener(type,listener[,useCapture])第三个参数如果是true,则表示在事件捕获阶段调用事件处理程序,如果是false(不写则默认false),表示在事件冒泡阶段调用事件处理程序

实际开发中更关注的是事件冒泡。很少关注事件捕获

有些事件是没有冒泡的,如onblur,onfocus,onmouseenter,onmouseleave;

<div class="father">
       <div class="son">son</div>
   </div>
   <script>
       var son=document.querySelector('.son');
       son.addEventListener('click',function() {
           alert('22');
       },true)
       var father=document.querySelector('.father');
       father.addEventListener('click',function() {
           alert('33');
       },true)
   </script>

事件对象

官方解释:event对象代表事件的状态,比如键盘按键的状态,鼠标的位置,鼠标按钮的状态

简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,他有很多的属性和方法<body>

    <div></div>
    <script>
        var div=document.querySelector('div');
        div.onclick=function(event) {//小括号里面写入e或event,监听函数同
            console.log(event);
        }
        //事件对象只有有了事件才会存在,是系统自动创建的,不需要我们传递参数,
        //事件对象我们可以自己命名,但比较常用e,event,evt
        //事件对象存在兼容性问题,ie678通过windows.event
     //event是形参,不需要传递实参进去
     //兼容性问题解决 e=e||windows.event
    </script>
</body>

<div>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </div>
    <script>
        var ul=document.querySelector('ul');
        ul.onclick=function(e) {
            //this指向的是绑定的对象
            console.log(this);//返回ul
            //e.target指向的是我们点击的对象
            console.log(e.target);//返回li(如果点击的是li)
            
        }
    </script>

阻止事件冒泡

利用事件对象里面的stopPropagation()方法

示例

<div class="father">
        <div class="son">son</div>
    </div>
    <script>
        var son = document.querySelector('.son');
        son.addEventListener('click',function(e) {
            alert('22');
            e.stopPropagation();//点击son之后终止son冒泡
        },false);
        var father=document.querySelector('.father');
        father.addEventListener('click',function() {
            alert('33');
        },false);
    </script>

事件委托(代理,委派)

事件冒泡本身的特性,会带来坏处,也会带来好处,需要我们灵活应用

事件委托原理(记住)

不是给每个子节点单独设置事件监听器,而是事件监听器设置在其父结点上,然后利用冒泡原理影响设置每个子节点

 <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        //为li添加点击效果
        //事件委托的核心原理,给父节点添加监听器,运用事件冒泡影响每一个子节点
        var ul=document.querySelector('ul');
        ul.addEventListener('click',function(e) {
            e.target.style.backgroundColor="pink";
        })
    </script>    

禁止鼠标右键菜单

<body>
   文字
   <script>
       document.addEventListener('contextmenu',function(e){
           e.preventDefault();
       })
   </script>
</body>

禁止鼠标选中

<body>
   文字
   <script>
       document.addEventListener('selectstart',function(e){
           e.preventDefault();
       })
   </script>
</body>

常用的鼠标事件

event对象代表事件的状态,跟事件相关的一系列信息的集合,现阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeybordEvent

鼠标事件对象

 

 

<script>
      document.addEventListener('click',function(e) {
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------');
            console.log(e.pageX);
            console.log(e.pageY);
      })
   </script>

案例:设置图片一直跟随鼠标

 

 

 <img src="1.jpg" alt="图片">
   <script>
       var pic=document.querySelector('img');
      document.addEventListener('mousemove',function(e) {//document.对文档出发
          //mousemove只要鼠标移动1像素,就会触发这个事情。
          var x =e.pageX;
          var y =e.pageY;
          //千万不要忘记给left和top添加px单位!!
          pic.style.left=x+'px';
          pic.style.top=y+'px';
      //如果想让图片位于鼠标居中位置,这里分别减去对应图片一半的大小即可 });
</script>

常用键盘事件

 

 这里仍要注意使用addEventListener时,不带on

三个事件的执行顺序,keydown-keypress-keyup

keyCode判断用户按下了哪个键,可以得到按下键的相应的ascii值

<script>
       document.addEventListener('keyup',function(e) {
           console.log(e.keyCode);
           //keyup和keydown事件不区分大小写,a与A得到的都是65
       //keypress区分字母的大小写
}); </script>

blinbling完美结束

posted @ 2020-03-15 14:56  echobbd  阅读(224)  评论(0编辑  收藏  举报