javascript - 点击ul下面的li,弹出当前li的index
PHP中文网
PHP中文网 2017-04-11 12:23:31
[JavaScript讨论组]

这个是之前面试的一道题,当时给的答案是类似下面这种:

var nodes = document.getElementsByTagName("li");
for(i = 0;i

然后回来网上搜了搜,结果发现答案基本就是这一种,当时那个面试官对我这答案感觉不满意,问我还有别的方法实现么,我说不知道= =

这里问问大家,要是你,你会怎么回答这到问题呢?

PHP中文网
PHP中文网

认证高级PHP讲师

全部回复(8)
大家讲道理

方式1. 使用闭包。

var ul = document.getElementsByTagName("ul")[0];  
var list = ul.getElementsByTagName("li");  

function foo(){  
    for(var i = 0, len = list.length; i < len; i++){  
        var that = list[i];  
        list[i].onclick = (function(k){  
            var info = that.innerHTML;  
            return function(){  
                alert(k + "----" + info);  
            };  
        })(i);  
    }  
}  

foo();  

方式2.事件代理

var ul = document.querySelector('ul');  
var list = document.querySelectorAll('ul li');  
  
ul.addEventListener('click', function(ev){  
    var ev = ev || window.event;  
    var target = ev.target || ev.srcElemnt;  
  
    for(var i = 0, len = list.length; i < len; i++){  
        if(list[i] == target){  
            alert(i + "----" + target.innerHTML);  
        }  
    }  
});  

方式3. 引入jQuery,使用其中的on或delegate进行事件绑定(它们都有事件代理的特性)

// delegate方法
$("ul").delegate("li", "click", function(){  
    var index = $(this).index();  
    var info = $(this).html();  
    alert(index + "----" + info);  
});  
 // on方法
$("ul").on("click", "li", function(){  
    var index = $(this).index();  
    var info = $(this).html();  
    alert(index + "----" + info);  
});  

方式4. 使用ES6中的新特性let来声明变量
用let来声明的变量将具有块级作用域,很明显可以达到要求,不过需要注意的是得加个'use strict'(使用严格模式)才会生效。

var ul = document.getElementsByTagName("ul")[0];  
var list = ul.getElementsByTagName("li");  
  
function foo(){'use strict'  
    for(let i = 0, len = list.length; i < len; i++){  
        list[i].onclick = function(){  
            alert(i + "----" + this.innerHTML);  
        }  
    }  
}  
foo();  
PHP中文网

事件代理?

<ul>
    <li id="li1">1</li>
    <li id="li2">2</li>
    <li id="li3">3</li>
    <li id="li4">4</li>
</ul>
var nodes = document.getElementsByTagName("ul");
    nodes[0].addEventListener('click', function(e){
        console.log(e.target.id.replace("li", ''));
    });
ringa_lee

在这堆li元素的父元素上挂事件可能是更好的实现方式。

ringa_lee

首先你得东西有一个很大的问题,就是你获取的是页面上所有的li,所以console.log(i)输出的是在所有li中,当前的是第几个。

至于要输出index,几种写法:
不过现在好像更推荐addEventListener来添加事件,然后选择器用的更精确一点。

  1. 闭包,和你的一样。

  2. let来声明i

  3. 或者通过js的方法获取当前liindex

for(let node of nodes) {
    node.addEventListener("click", function(){ 
        console.log(Array.prototype.indexOf.call(this.parentNode
    .children, this)); 
    })
}
ringa_lee
  • 这个问题的考察点是闭包,你的答案已经做到了。

  • 还可以改进的就是绑定事件的方式,做到兼容旧版本的IE。

  • 还可能会有要求输出当前 UL中的li次序。

  • 如果li很多,每个都绑定事件太占内存了,需要用到事件代理。但是使用代理后每次点击都遍历一遍太浪费,可以第一次遍历后缓存起来(像jQuery一样),只要DOM结构不改变,下次点击可以直接返回缓存中的li了。

高洛峰

闭包太占用内存,如果考虑优化效果的话,可以试试利用自定义属性在for循环里边的第一句加上一个nodes[i].index = i;这样的话不会形成私有作用域内存不释放。还能利用自定义属性找到正确的索引。

天蓬老师
    <ul class="menu_list">
        <li>demo1</li>
        <li>demo2</li>
        <li>demo3</li>
    </ul>
    <script type="text/javascript">
    // 不想 用 闭包 的 话 不是 还有个 最常用的 吗 像这样的 以前 楼主 不经常 看到 吗、、、、、、
         // 或者 用 es6 let 的 块级 作用域
    for (var i = 0,oLi = document.querySelectorAll('.menu_list > li'),l = oLi.length;i < l;i++){
        oLi[i].index = i;
        oLi[i].onclick = function(){
            alert(~~this.index);
        };
    }
      </script>
ringa_lee

这题是考性能优化的吧?
用事件委托来答题应该好点

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号