【问题标题】:Being able to re-use to a JavaScript function能够重用 JavaScript 函数
【发布时间】:2022-11-29 01:09:03
【问题描述】:

一段时间以来,我一直在使用一个非常有用的 JavaScript 函数,但并不完全确定来源(可能在 Stack Overflow 上),但它肯定不是我写的东西,因为我对 JS 知之甚少。

它基本上根据所选的选择选项显示表单部分。它在使用一次时很有用,但是我现在的情况是我有一个相当复杂的形式并且需要多次使用它。显而易见的方法是复制\粘贴并简单地重命名每个函数,从而使其独一无二。但是,这是很多重复的代码。

我的问题是如果我重新使用它,两个选择字段会相互干扰。我试过看看我是否可以锁定它,或者它是否正在使用 ID,但我正在努力。

最小的,可重现的例子:

var current;

function reveal(element) {
  if (current !== undefined) {
    var chosen = document.getElementById(current);
    chosen.classList.remove("visible");
    chosen.classList.add("hidden");
  }
  
  var fetchMe = element.options[element.selectedIndex].getAttribute('data-show');
  
  if (fetchMe !== null) {
    current = fetchMe;
    var fetched = document.getElementById(fetchMe);
    fetched.classList.remove("hidden");
    fetched.classList.add("visible");
  }
}
.hidden {
  display: none;
}

.visible {
  display: block;
}
<h2>Knowledge</h2>

<select onchange="reveal(this)">
  <option>Select...</option>
  <option data-show="known">Known</option>
  <option data-show="unknown">Unknown</option>
</select>

<div class="hidden" id="known">
  <input type="text" name="known" value="Known">
</div>

<div class="hidden" id="unknown">
  <input type="text" name="unknown" value="Unknown">
</div>

<h2>Superheroes</h2>

<select onchange="reveal(this)">
  <option>Select...</option>
  <option data-show="batman">Batman</option>
  <option data-show="superman">Superman</option>
</select>

<div class="hidden" id="batman">
  <input type="text" name="batman" value="Batman">
</div>

<div class="hidden" id="superman">
  <input type="text" name="supermann" value="Superman">
</div>

理想情况下我想对其进行 ringfence,或者使用 ID 来限制它。

也可用 a Fiddle

【问题讨论】:

    标签: javascript


    【解决方案1】:

    我保留了你的逻辑。
    现在您的选择需要 id(此处以 id1、id2 为例)
    您的变量“current”现在是一个对象,其中每个属性都是 select 的 id

    小心使用“var”。您应该使用“const”或至少使用“let”来避免副作用

    var current = {};
    
    function reveal(element) {
      const idSelect = element.id
      if (current[idSelect] !== undefined) {
        var chosen = document.getElementById(current[idSelect]);
        chosen.classList.remove("visible");
        chosen.classList.add("hidden");
      }
      var fetchMe = element.options[element.selectedIndex].getAttribute('data-show');
      if (fetchMe !== null) {
        current[idSelect] = fetchMe;
        var fetched = document.getElementById(fetchMe);
        fetched.classList.remove("hidden");
        fetched.classList.add("visible");
      }
    }
    .hidden {
      display: none;
    }
    
    .visible {
      display: block;
    }
    <h2>Knowledge</h2>
    
    <select onchange="reveal(this)" id="id1">
      <option>Select...</option>
      <option data-show="known">Known</option>
      <option data-show="unknown">Unknown</option>
    </select>
    
    <div class="hidden" id="known">
      <input type="text" name="known" value="Known">
    </div>
    
    <div class="hidden" id="unknown">
      <input type="text" name="unknown" value="Unknown">
    </div>
    
    <h2>Superheroes</h2>
    
    <select onchange="reveal(this)" id="id2">
      <option>Select...</option>
      <option data-show="batman">Batman</option>
      <option data-show="superman">Superman</option>
    </select>
    
    <div class="hidden" id="batman">
      <input type="text" name="batman" value="Batman">
    </div>
    
    <div class="hidden" id="superman">
      <input type="text" name="supermann" value="Superman">
    </div>

    【讨论】:

    • 太棒了,非常感谢。我能够替换我已经拥有的东西,表格的其余部分就开始工作了。我将很快花一些时间研究 var、const 和 let。
    【解决方案2】:

    我不确定外部变量的意义是什么,因为您在选项属性中拥有所需的数据。这可以大大简化,甚至不需要争论。

    此外,让我们使用事件侦听器而不是内联 JavaScript。

    function reveal() {
      // hide all
      document.querySelectorAll('.hidden').forEach(el => {
        el.style.display = 'none';
      });
    
      // show for each select
      document.querySelectorAll('select').forEach(el => {
        const selectedVal = el.selectedOptions[0].dataset.show;
    
        if (selectedVal) {
          document.getElementById(selectedVal).style.display = 'block';
        }
      });
    }
    
    document.querySelectorAll('select.special').forEach(el => {
      el.addEventListener('change', reveal);
    });
    .hidden {
      display: none;
    }
    <h2>Knowledge</h2>
    
    <select class="special">
      <option>Select...</option>
      <option data-show="known">Known</option>
      <option data-show="unknown">Unknown</option>
    </select>
    
    <div class="hidden" id="known">
      <input type="text" name="known" value="Known">
    </div>
    
    <div class="hidden" id="unknown">
      <input type="text" name="unknown" value="Unknown">
    </div>
    
    <h2>Superheroes</h2>
    
    <select class="special">
      <option>Select...</option>
      <option data-show="batman">Batman</option>
      <option data-show="superman">Superman</option>
    </select>
    
    <div class="hidden" id="batman">
      <input type="text" name="batman" value="Batman">
    </div>
    
    <div class="hidden" id="superman">
      <input type="text" name="supermann" value="Superman">
    </div>

    【讨论】:

    • 您不害怕循环每个选择的每个值并对它们执行操作会影响性能吗?
    • 仅当页面中有 10,000 个选择时。 :) 这就是数百万下拉菜单和手风琴结构的处理方式。这通常不是问题。
    • 我的意思是,这始终是争论的焦点,更容易/更快地处理“低”性能或相反的性能。即使在这种情况下你是对的,用户也可能看不出有什么不同
    【解决方案3】:

    不要将选定的输入保存在全局变量中,这会使函数难以重用,而是分别处理每个 select 选项:

    function reveal(element) {
      var options = element.options;
      for (var i = 0; i < options.length; i++) {
        var option = options[i].getAttribute('data-show');
        var chosen = option && document.getElementById(option);
        if (chosen !== null) {
          if (i === element.selectedIndex) {
            chosen.classList.remove("hidden");
            chosen.classList.add("visible");
          } else {
            chosen.classList.remove("visible");
            chosen.classList.add("hidden");
          }
        }
      }
    }
    .hidden {
      display: none;
    }
    
    .visible {
      display: block;
    }
    <h2>Knowledge</h2>
    
    <select onchange="reveal(this)">
      <option>Select...</option>
      <option data-show="known">Known</option>
      <option data-show="unknown">Unknown</option>
    </select>
    
    <div class="hidden" id="known">
      <input type="text" name="known" value="Known">
    </div>
    
    <div class="hidden" id="unknown">
      <input type="text" name="unknown" value="Unknown">
    </div>
    
    <h2>Superheroes</h2>
    
    <select onchange="reveal(this)">
      <option>Select...</option>
      <option data-show="batman">Batman</option>
      <option data-show="superman">Superman</option>
    </select>
    
    <div class="hidden" id="batman">
      <input type="text" name="batman" value="Batman">
    </div>
    
    <div class="hidden" id="superman">
      <input type="text" name="supermann" value="Superman">
    </div>

    【讨论】:

      猜你喜欢
      • 2012-05-29
      • 2020-01-31
      • 2012-09-13
      • 1970-01-01
      • 2012-06-09
      • 2019-08-11
      • 2020-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多