美文网首页
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