【问题标题】:Javascript get index of child on clickJavascript在点击时获取孩子的索引
【发布时间】:2020-06-23 02:03:54
【问题描述】:

我已向父级#carousel-thumbs 添加了一个点击事件。

carouselThumbsContainer.onclick = function(ev) {
    var target = ev.target;    // which child was actually clicked
}

<ul id="carousel-thumbs" class="l-grid">
    <li class="active"><a class="active" href="#"><img src="img/carousel-1-th.jpg" /></a></li>
    <li><a href="#"><img src="img/carousel-2-th.jpg" /></a></li>
    <li><a href="#"><img src="img/carousel-3-th.jpg" /></a></li>
    <li><a href="#"><img src="img/carousel-4-th.jpg" /></a></li>
</ul>

我想返回被点击元素相对于其父元素的索引。所以如果用户点击了第二个

  • 我会得到 1。

    //////////////////////////////////// 当前可行但我希望简化的解决方案:

        //Add a click event to each thumn in the thumbs container
    for (var j = 0, len = carouselThumbsContainer.children.length; j < len; j++){
        (function(index){
            carouselThumbsContainer.children[j].onclick = function(){
                  console.log(index);
            }    
        })(j);
    }
    

    对 Javascript 不太了解,我认为一定有更简单的方法,但也许没有。

  • 【问题讨论】:

    • 点击的孩子的索引是什么意思?你的意思是它的子位置?即第一个孩子,第二个孩子等?
    • 是的,它的子位置。父级是一个
        ,我想返回被点击的
      • 的索引。

    标签: javascript


    【解决方案1】:

    试试这个(另请阅读:What is DOM Event delegation?):

    carouselThumbsContainer.onclick = function (e) {
        var tgt = e.target, i = 0, items;
        if (tgt === this) return;
        items = children(this);
        while (tgt.parentNode !== this) tgt = tgt.parentNode;
        while (items[i] !== tgt) i++;
        alert(i);
    };
    
    function children(el) {
        var i = 0, children = [], child;
        while (child = el.childNodes[i++]) {
            if (child.nodeType === 1) children.push(child);
        }
        return children;
    }
    

    这是一个演示:

    var hit = false,
        ul = document.getElementsByTagName('ul')[0],
        addButton = document.getElementsByTagName('a')[0],
        toggleButton = document.getElementsByTagName('a')[1],
        active = null;
    
    ul.onclick = function (e) {
        var i = 0, tgt = e.target, items;
        if (tgt === this) return;
        items = children(ul);
        while (tgt.parentNode !== this) tgt = tgt.parentNode;
        while (items[i] !== tgt) i++;
        hit = true; // for debug purposes only
        if (active) active.className = '';
        (active = tgt).className = 'active';
        output('index : ' + i);
    };
    
    addButton.onclick = function () {
        var li = document.createElement('li'),
            n = children(ul).length + 1;
        li.innerHTML = '<a href="#">item ' + n + '</a>';
        li.innerHTML += '<ul><li><a href="#">sub item</a></li></ul>';
        ul.appendChild(li);
        hit = true;
    };
    
    toggleButton.onclick = function () {
        ul.className = ul.className ? '' : 'sublists';
        hit = true;
    };
    
    document.onclick = function (e) {
        e.preventDefault();
        if (hit) hit = false;
        else output('index : none');
    };
    
    // populate the UL
    
    var i = 0;
    while (i++ < 5) addButton.onclick();
    hit = false;
    
    // helpers
    
    function children(el) {
        var i = 0, children = [], child;
        while (child = el.childNodes[i++]) {
            if (child.nodeType === 1) children.push(child);
        }
        return children;
    }
    
    function output(s) {
        document.getElementsByTagName('span')[0].innerHTML = s;
    }
    body { font-family: Arial; }
    div { width: 210px; padding-left: .5em; }
    p a { float: right; color: blue; margin-left: .5em; }
    ul { border: 1px solid black; padding: 1em 1em 1em 2.5em; }
    ul ul { display: none; }
    ul.sublists ul { display: block; }
    li a { display: block; color: inherit; text-decoration: none; }
    li a { border-right: 90px solid transparent; }
    li a:hover { border-right-color: blue; }
    li.active a { border-right-color: black; }
    li li a { border-right-width: 18px; }
    <div>
        <p>
            <a href="#" title="add a new item">add</a>
            <a href="#" title="toggle sub lists">toggle</a>
            <span><i>click any item</i></span>
        </p>
        <ul></ul>
    </div>

    逐行点击处理程序

    演员

    var tgt = e.target, i = 0, items; // and `this`
    

    this 是 UL 本身。 e.target 是发起事件的 DOM 元素。它可以是 UL 或 UL 本身的任何后代(在本例中为 e.target = this)。 i 保存被点击项目的索引。 items 代表 LI 是 UL 的直接子级。

    故事

    如果目标是 UL 本身,则退出函数:

    if (tgt === this) return;
    

    获取作为 UL 的直接子级的 LI:

    items = children(this);
    

    通过目标的祖先冒泡直到到达最上面的 LI:

    while (tgt.parentNode !== this) tgt = tgt.parentNode;
    

    增加索引直到目标匹配 LI 之一:

    while (items[i] !== tgt) i++;
    

    提醒索引:

    alert(i);
    

    【讨论】:

      【解决方案2】:

      您可以改变数组 indexOf 函数的用途,并在父母的孩子中找到目标的索引:

      var el = e.target;
      while (el.tagName.toLowerCase() != "li") {
          el = el.parentNode;
      }
      
      [].indexOf.call(el.parentNode.children, el);
      

      或者只使用 for 循环并遍历 children

      演示:http://jsfiddle.net/SFke7/2/

      【讨论】:

      • 插入时总是为零:carouselThumbsContainer.onclick = function(e) { //var target = ev.target; // 实际点击了哪个孩子 alert([].indexOf.call(e.target.parentNode.children, e.target)); }
      • 是的,我在您发布代码后才意识到。您需要遍历树以获取 li,然后将其与 父级进行比较。否则,您将获得 a 元素的索引,该元素将始终为零,因为它是该级别的唯一元素。
      • 我对 Javascript 还是很陌生,如果你愿意提供一个很棒的例子的话。
      • 就在那儿。如何指定特定 ID 的 ul?小提琴正在查看页面上的第一个 ul 实例。在 Jquery 中,我会寻找带有 id 的 ul,不知道如何在 Javascript 中链接它。
      • @JacobLauritzen 很高兴知道。应该提到我需要对 IE7+ 的支持。我有一个可行的解决方案,但正在寻找更优雅的东西。将在上面发布我的原始解决方案。感谢大家的帮助。
      【解决方案3】:

      适用于 IE >= 9

      var index = Array.prototype.indexOf.call(this.children, ev.target);
      

      你可以在这里看到它的工作原理:http://jsfiddle.net/mBg98/

      【讨论】:

      • 拍摄,需要支持IE7+
      • 您可以将其添加到您的代码中以使 indexOf 在 IE 中工作:stackoverflow.com/a/11473036/1630044 但对于这样一个简单的任务来说,这可能有点矫枉过正
      猜你喜欢
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 1970-01-01
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      • 2018-01-31
      相关资源
      最近更新 更多