【问题标题】:onclick not firing on first click, sortable list, JavaScriptonclick 在第一次点击时未触发,可排序列表,JavaScript
【发布时间】:2017-08-06 17:32:56
【问题描述】:

我正在尝试制作一个列表,其中每一行都可以通过按下按钮来上升或下降。

我在按钮上使用了onclick方法,参数为'this'。

当页面加载时,需要点击几下才能触发事件。

之后,它需要点击 1 到 3 次。

这是为什么呢?

<!doctype html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">    

    <title>Schedule</title>
</head>
<body>
<div id="eXes">
  <div class="eX">
    1
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div>
  <div class="eX">
    2
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div>
  <div class="eX">
    3
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div>
</div>

<script type="text/javascript">
    function moveUp(el) {
        var selected = el.parentNode;
        var previous = el.parentNode.previousSibling;
        document.getElementById("eXes").insertBefore(selected, previous);
    }
</script>
<script type="text/javascript">
    function moveDown(el) {
        var selected = el.parentNode;
        var next = el.parentNode.nextSibling;
        document.getElementById("eXes").insertBefore(selected, next.nextSibling);
    }
</script>
</body>
</html>

直播代码https://www.w3schools.com/code/tryit.asp?filename=FIAIQO31H90L

【问题讨论】:

  • 首先,感谢所有回复。问题确实是空白被视为文本节点。我在link 找到的最简单和最优雅的修复方法是用 previous/nextElementSibling 替换 previous/nextSibling,尽管我还没有测试浏览器支持。附言@Risa__B 的 Array.prototype.slice.apply 方法对我来说是一个不错的新东西,尽管与问题并不完全相关。

标签: javascript onclick


【解决方案1】:

如果你 console.log el.parentNode.previousSilbing,你会看到你在每个 div 之间有一个 'nextLine' el,所以只需删除它就可以了,但会使 html 看起来很丑。

<!doctype html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
  	
	<title>Rota Schedule</title>
</head>
<body>
<div id="eXes">
  <div id='1' class="eX">
    1
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div><div div id='2'  class="eX">
    2
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div><div div id='3' class="eX">
    3
    <button class="up" onclick="moveUp(this)">up</button>
    <button class="down" onclick="moveDown(this)">down</button>
  </div>
</div>

<script type="text/javascript">
	function moveUp(el) {
    console.log('click',el.parentNode,el.parentNode.previousSibling)
		var selected = el.parentNode;
		var previous = el.parentNode.previousSibling;
		document.getElementById("eXes").insertBefore(selected, previous);
	}
</script>
<script type="text/javascript">
	function moveDown(el) {
		var selected = el.parentNode;
		var next = el.parentNode.nextSibling;
		document.getElementById("eXes").insertBefore(selected, next.nextSibling);
	}
</script>
</body>
</html>

【讨论】:

    【解决方案2】:

    您的问题是每个 div 之间的空白。浏览器将其视为 textNode ,因此当您最初向上或向下移动元素时,实际上只是将其与空白交换。一旦你上下点击了 2-3 次,你就有效地将空白“排序”到了 dom 堆栈的底部,然后你就不再看到问题了。

    一个快速的解决方法是通过更改标记来关闭和打开 div,而不是在新行上,从而删除空白。

    您可以在此处阅读有关空白的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace_in_the_DOM

    【讨论】:

      【解决方案3】:

      尝试以下操作,我将在按钮的每个向下或向上删除事件 onClick,然后我将使用 Arrary.prototype 和 forEach 来选择元素:

      Array.prototype.slice.apply(document.querySelectorAll('.up')).forEach(function (el){
      el.addEventListener('click',function(){
      
       var selected = el.parentNode,
           previous = el.parentNode.previousSibling;
             document.getElementById("eXes").insertBefore(selected, previous);
      
      });
      });
      Array.prototype.slice.apply(document.querySelectorAll('.down')).forEach(function (el){
      el.addEventListener('click',function(){
      
      var selected = el.parentNode,
          next = el.parentNode.nextSibling;
      if(next == undefined){
      next =  document.getElementById("eXes").firstChild;
      }    document.getElementById("eXes").insertBefore(selected, next.nextSibling);
              
      });
      });
      <div id="eXes">
        <div class="eX">
          1
          <button class="up">up</button>
          <button class="down">down</button>
        </div>
        <div class="eX">
          2
          <button class="up">up</button>
          <button class="down">down</button>
        </div>
        <div class="eX">
          3
          <button class="up">up</button>
          <button class="down">down</button>
        </div>
      </div>

      ForEach

      foreach 函数对数组中的每个元素执行一次回调函数,请访问此链接以获取更多信息: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

      【讨论】:

        【解决方案4】:

        previsousSibling 和 nextSibling 返回前一个或后一个兄弟。在您的情况下,每个

        之间都有一个换行符
        ...
        </ div>
        <div class="ex">
        ...
        

        所以如果你 console.log(previous) 你的结果将是一个文本而不是元素。

        如果你这样做,你的问题将得到解决

        <div class="eX">
        1
        <button class="up" onclick="moveUp(this)">up</button>
        <button class="down" onclick="moveDown(this)">down</button>
        </div><div class="eX">
         2
        <button class="up" onclick="moveUp(this)">up</button>
        <button class="down" onclick="moveDown(this)">down</button>
        </div><div class="eX">
         3
        <button class="up" onclick="moveUp(this)">up</button>
        <button class="down" onclick="moveDown(this)">down</button>
        </div>
        

        但这会使您的代码可见性最差。

        你应该做的是使用函数来获取好的元素。在您的情况下,您必须将 previsousSibling 和 nextSibing 替换为

        function previousElementSibling( elem ) {
        
        do {
        
            elem = elem.previousSibling;
        
        } while ( elem && elem.nodeType !== 1 );
        
        return elem;
        }
        
        function nextElementSibling( elem ) {
        
        do {
        
            elem = elem.nextSibling;
        
        } while ( elem && elem.nodeType !== 1 );
        
        return elem;
        }
        

        【讨论】:

          猜你喜欢
          • 2022-11-22
          • 2011-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多