美文网首页
JS点击事件中的for与this

JS点击事件中的for与this

作者: liwuwuzhi | 来源:发表于2017-12-02 16:22 被阅读0次

    我们先来做一个简单案例,功能描述:有一排a标签,当点击时要弹出该标签的索引值。先思考下怎么做:
    (1)循环所有a标签i,为其添加点击事件
    (2)点击事件里在循环一遍所有a标签j,如果点击的j和循环的i相同的话我们就弹出j//?为什么要再循环一遍呢?来看看下面代码

    
    <body>
      <ul id="friedslink">
          <li><a href="#">链接1</a></li>
          <li><a href="#">链接2</a></li>
          <li><a href="#">链接3</a></li>
          <li><a href="#">链接4</a></li>
      </ul>
    </body>
    <script type="text/javascript">
    
    /**
    * 函数:index(self,obj)
    * 参数:self:当前对象,obj:整体对象 
    * 功能:取得参数对象在元素组中的位置索引
    * 返回:Number
    **/ 
    var index = function(self,obj){  
      for(var i=0;i < obj.length;i++){
          if(obj[i]==self){
          return i;
          }
      }
    }
    var links = document.getElementById("friedslink").getElementsByTagName("a");
    for(var i =0;i < links.length;i++){
        links[i].onclick = function(){
            var i = index(this,links);
            console.log(i);
            return false;//阻止默认动作。
        }
    }
    </script>
    
    图一.png

    此时点击哪个链接就弹出该链接所在的标签堆里的索引值。

    如果不循环第二次会怎么样?依旧上面的代码,把引入index函数的语句注释掉看看

    //var i = index(this,links);
    

    此时再去点击链接,弹出的却全都是4,为什么呢?这里要储备的知识有两点:
    (1)事件里的函数会被放到消息队列,而循环是同步的,所以当页面打开时代码会一步步向下执行。当i为4时不符合条件,停止循环
    (2)for循环中定义的变量i相当于是全局的变量,当我们去点击按钮时,循环已经执行完了,此时获取到的i就是循环结束后的4

    (3)事件里的this代表的是调用该事件的对象,打印出此时的this看看

    for(var i =0;i < links.length;i++){
        links[i].onclick = function(){
            //var i = index(this,links);
            console.log(links);
            console.log(this);
            console.log(i)
            return false;//阻止默认动作。
        }
    }
    console.log('我是不符合条件的i:',i)
    
    图二.png
    我点击了链接1this指的是<li><a href="#">链接1</a></li>

    再练看看index函数

    var index = function(self,obj){  
      for(var i=0;i < obj.length;i++){
          if(obj[i]==self){
          console.log(obj[i]);//<li><a href="#">链接1</a></li>
          console.log(self);//<li><a href="#">链接1</a></li>
          return i;
          }
      }
    }
    

    我们再循环一遍时,去匹配拿this与一堆链接去对比,相同时就返回与this相同的那个链接在一堆链接中的索引值。

    这种方法是可行,却不是优秀的代码,毕竟循环了两次,那有什么比较好的方法呢?
    我们打印出 链接的数组console.log(links);如图二,把数组展开是怎样的呢?每个链接都是一个对象,对象里包含很多属性,
    那我们不妨在
    (1)第一次循环的时候就给每个链接对象都添加一个index属性,并且让index属性等于此时循环的i值(即该对象在数组中的索引值)
    (2)我们说过事件里的this代表的是点击的对象,而我在循环的时候已经给每个对象的添加了index属性,那在事件里用this.index是不是就可以得到点击对象的index值里,而这个值恰好与该对象在数组里的索引值一样(因为我们前面定义了links[i[.index = 1)
    来看看改进的代码吧。

    <html>
    <body>
    <ul id="friedslink">
      <li><a href="#">链接1</a></li>
      <li><a href="#">链接2</a></li>
      <li><a href="#">链接3</a></li>
      <li><a href="#">链接4</a></li>
    </ul>
    <script type="text/javascript">
    
    var links = document.getElementById("friedslink").getElementsByTagName("a");
    for(var i=0;i<links.length;i++){
        links[i].index = i;//给每个a标签对象添加index属性,并把索引值赋值给它
        links[i].onclick = function(){
        
            console.log(this.index);
            return false;
        }
    }
    console.log('我是不符合条件的i:',i)
    </script>
    </body>
    </html>
    

    点击事件里的this.index就是对象自己的index属性,也就是我们赋值给它的索引值,如果还不是很理解,看看下图


    图三.png

    当打开数组里的a对象,能看到到里面的我们给它添加的index属性。




    很多时候我们都会要用到这种技术,例如在选项卡里,点击tab时下面的内容框跟着跳转,是怎么做到的呢?先来看看html

    <style>
    body,ul,li{margin:0; padding:0; font:12px/1.5 arial;}
    ul,li{list-style:none;}
    .wrap{width:500px;height: 400px; margin:20px auto;}
    #tab_t li{float:left;box-sizing: border-box; width:25%; height:25px;line-height:25px; text-align:center; border:1px solid #aaa;}
    #tab_t li.act{background:#abcdef;}
    #tab_c div{border:1px solid #ccc;width:100%;height:300px;display: none;}
    #tab_c div.show{display: block;}
    </style>
    </head>
    <body>
    
      <div class="wrap">
          <ul id="tab_t">
              <li class="act">选择1</li>
              <li>选择2</li>
              <li>选择3</li>
              <li>选择4</li>
          </ul>
          <div id="tab_c">
              <div class="show">内容1</div>
              <div>内容2</div>
              <div>内容3</div>
              <div>内容4</div>
          </div>
      </div>  
      
    </body>
    
    图四.png

    如何做到点击点击li标签的时候下面的div也跟着一起跳转呢?那是不是要用到tab的下标,那tab的下标是怎么跟con联系起来的?思路如下
    要明白一点:循环是页面打开时就进行的,当我们去点击时,循环已经结束了,此时我们去获取的i的值为不符合循环条件的4
    (1)获取索引的tab标签tab_t_li,和所有的con标签tab_c_li;
    (2)循环tab标签的数组tab_t_li,并为每个li标签添加index属性;
    (3)每次点击时都循环所以的tab和con,把他们的class样式去掉,然后为点击的对象(tab)和与该tab有相同索引的con添加class样式。
    (4)点击的对象(tab)的索引值获取方法tab_t_li[this.index]

    看看下面代码:

    window.onload = function(){
      var tab_t = document.getElementById("tab_t");
      var tab_t_li = tab_t.getElementsByTagName("li");
      var tab_c = document.getElementById("tab_c");
      var tab_c_li = tab_c.getElementsByTagName("div");
      var len = tab_t_li.length;
      var i=0;
    
      for(i=0; i<len; i++){
        tab_t_li[i].index = i;//给tab_t_li添加index属性,并将索引值赋给它
        tab_t_li[i].onclick = function(i){
    
          /*
          这里的this指的是调用该函数的对象tab_t_li[i],而这个对象我们给它添加了index属性,且该index属性的值等于tab_t_li[i]的i值。
          该对象调用了点击事件,事件里的this指向的就是该对象,那么可以用this.index来获得该对象在tab_t_li数组里索引值
          */
          for(i=0; i<len; i++){
            tab_t_li[i].className = '';
            tab_c_li[i].className = '';
          }
          console.log(this.index)
          tab_t_li[this.index].className = 'act';
          tab_c_li[this.index].className = 'show';
    
          /*
          //为什么要用this.index,不可以直接用i吗?对于这个疑问,可以先看看输出的i是什么
          console.log(i);
          //4,到最后i = 4,不符合i<len条件,停止循环
          console.log(tab_t_li[i]);
          //undefined ,循环完后,全局的变量i的值为4,而tab_t_li[length-1] = 3,所以tab_t_li[4]是不存在的,所以返回undefined。既然tab_t_li[4]都为undefined了,那么tab_t_li[4].classNama自然也是不存在的,所以下面两条语句都是错误的。
    
          tab_t_li[i].className = 'act';//Cannot set property 'className' of undefined
          tab_c_li[i].className = 'block';//Cannot set property 'className' of undefined
          */
        }
      }  
    }
    

    或者用这种方式,但是原理都是一样的,看下面代码:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            .active{background: #9cc;}
            .div2{width:300px;height: 200px;border:1px solid red;display: none;}
        </style>
    </head>
    <body>
    <div id="div1">
        <input type="button" value="1" class="active"/>
        <input type="button" value="2"/>
        <input type="button" value="3"/> 
        <input type="button" value="4"/>
        <div class="div2" style="display:block;">11</div>
        <div class="div2">22</div>
        <div class="div2">33</div>
        <div class="div2">44</div>
    </div>
    
    <script type="text/javascript">
        
        var box = document.getElementById("div1");
        var btn = box.getElementsByTagName("input");
        var con = box.getElementsByTagName("div");
    
        for(var i=0;i<btn.length;i++){
            btn[i].index = i;
            btn[i].onclick = function(){
    
                for(var i = 0;i<btn.length;i++){
                    btn[i].className = "";
                    con[i].style.display = "none";
                }
                this.className = "active";
                con[this.index].style.display = "block";
            }
        }
    </script>
    </body>
    </html>
    
    图五.png









    明白了这个原理之后,你会发现其实大多数的tab选项卡,一级菜单,二级菜单走的都是这个套路,下面我们来看看一级菜单。
    一级菜单就是他自己,不用跟谁去相关联,但是也要用到for循环,和点击事件(或者鼠标移入移出事件)那么就要用到this了。

    <ul id="nav">
        <li><a href="#">aaa</a></li>
        <li><a href="#">aaa</a></li>
        <li><a href="#">aaa</a></li>
        <li><a href="#">aaa</a></li>
    </ul>
    
    <script type="text/javascript">
    
        var nav = document.getElementById("nav");
        var navLi = nav.getElementsByTagName("li");
    
        for(var i = 0;i<navLi.length;i++){
    
            navLi[i].onmouseover = function(){
                //this.style.background = '#f00'
                this.setAttribute("class","demo");
            }
    
            navLi[i].onmouseout = function(){
                //this.style.background = '#fff'
                this.setAttribute("class","");
            }
        }
    </script>
    
    一级菜单.png

    再来看看二级菜单

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style type="text/css">
             *{margin:0;padding:0;font-size:13px;list-style:none;}
            .menu{width:210px;margin:50px auto;border:1px solid #ccc;}
            .menu p{height:25px;line-height:25px;font-weight:bold;background:#eee;border-bottom:1px solid #ccc;cursor:pointer;padding-left:5px;}
            .menu div ul{display:none;}
            .menu li{height:24px;line-height:24px;padding-left:5px;}
        </style>
    </head>
    
    <body>
    
        <div class="menu" id="menu">
            <div>
                <p>Web前端</p>
                <ul style="display:block">
                    <li>JavaScript</li>
                    <li>DIV+CSS</li>
                    <li>jQuery</li>
                </ul>
            </div>
            <div>
                <p>后台脚本</p>
                <ul>
                    <li>PHP</li>
                    <li>ASP.net</li>
                    <li>JSP</li>
                </ul>
            </div>
            <div>
                <p>前端框架</p>
                <ul>
                    <li>Extjs</li>
                    <li>Esspress</li>
                    <li>YUI</li>
                </ul>
            </div>
        </div>
    </body>
    
    <script type="text/javascript">
    window.onload=function(){
        var menu=document.getElementById('menu'),
            ps=menu.getElementsByTagName('p'),
            uls=menu.getElementsByTagName('ul');
        for(var i in ps){
            ps[i].id=i;
            ps[i].onclick=function(){
                var u=uls[this.id];
                if(u.style.display=='block'){
                    u.style.display='none';
                }else{
                    u.style.display='block';
                }   
            }
        }
    }
    </script>
    </html>
    
    竖向折叠二级菜单.png

    相关文章

      网友评论

          本文标题:JS点击事件中的for与this

          本文链接:https://www.haomeiwen.com/subject/gyxnbxtx.html