【问题标题】:How can you manage CSS selectors for identical code included multiple times in the same page?如何管理同一页面中多次包含的相同代码的 CSS 选择器?
【发布时间】:2021-02-15 20:35:34
【问题描述】:

我经常创建在页面顶部使用传统选项卡的 Web 应用程序。执行此操作时,我遇到了一个常见问题,我一直无法找到优雅的解决方案。

问题是用户可以在同一页面上的两个单独选项卡中加载相同的内容。然后,这两个不同选项卡上的任何 HTML ID 都会发生冲突,从而导致引用其中一个 ID 的任何 JavaScript 在第二个选项卡上失败。此外,任何在其中一个页面上引用类的 JavaScript 都会影响所有选项卡上的元素,而我真的只希望它影响当前选项卡。

例如,如果我在同一个页面中包含此代码块两次怎么办?

<style>
    #container { margin; 20px; }
    #message { background: red; }
</style>

<div id='container'>
    <span id='message'>This was from an include file</span>
    <button id='changeColorBtn'>Change color</button>
</div>

<script>
    $('#changeColorBtn').click(() => $('#message').css('background', 'blue'))
</script>

JSFIDDLE 说明问题:https://jsfiddle.net/dillydadally/2njcq9py/

我过去曾尝试或考虑过三种解决此问题的方法:

  1. 我尝试使用 PHP 将页面 ID 附加到包含内容中的每个元素。写出来会变得又快又烦人。

  2. 我尝试将每个选项卡设为 iframe。起初,这似乎运作良好,但很快就变成了管理方面的噩梦,在同一页面上打开了如此多的 iframe,有时需要相互通信和共享数据。我遇到了多个问题并决定不再尝试这种方法。

  3. 我考虑将包含内容的每个实例包装在具有唯一 ID 的单个元素中,但我决定我会遇到与上述选项 1 类似的问题。每个 CSS 选择器都必须首先拥有带有 ID 的元素,这又一次创建了混乱的代码,并可能使用大量的多深度 JQuery 选择器减慢页面速度。此外,在同一页面上仍然会有多个具有相同 ID 的元素(尽管我不确定这是否重要,因为每个选择器都应该包含一个父元素)。

是否已经在我缺少的 HTML/CSS 中创建了一个元素或方法来解决这个问题?

【问题讨论】:

  • ids 只能使用一次,并且您的脚本只能在它找到的第一个上运行。您需要在每个按钮及其上一个消息框上使用不同的 id 或循环
  • ...如果评论不清楚,请尝试使用 class 而不是 id 并仅加载一次函数...可能的示例jsfiddle.net/hb4ecfxr
  • 是的,重复的 ID 值是无效的 HTML,而 jQuery 的编写期望您的 HTML 有效。修复 ID,只加载一次点击函数,使用事件委托来处理动态创建的元素。

标签: javascript php html jquery css


【解决方案1】:

您必须在具有相同样式的元素上使用类而不是 ID,并且您希望在文档中使用相同的 css 样式规则影响多次。

例如:


<div id="main"><!-- / The main ID is only used once in the document / -->
  <p class="par">
    Here is the first paragraph with the same style as the second
  </p>
  <p class="par">
    Here is the second paragraph with the same style as the first
  </p>
</div>

现在您的问题是影响文档中多次使用的同一类型的元素...

因为您将 span (message)button 作为一对放在同一个父元素下,所以您可以在事件侦听器中访问循环的索引使用被选中的节点列表来识别被按下的那个。

我在节点列表上使用 vanilla JS querySelectorAll()。您必须为具有相同标签名称的多个元素使用类。

我针对元素父类let message = document.querySelectorAll('.content span')let btn= document.querySelectorAll('.content button')。然后通过 forEach 循环运行节点,并使用 forEach 循环中的索引向按钮元素添加事件监听器。尽管此索引是 btn 元素的索引,但由于它们是配对的,因此它将使用来自 btn 的索引定位正确的 message 元素。

let btn = document.querySelectorAll('.container button');
let message = document.querySelectorAll('.container span');

btn.forEach((button, i) => {
  // in short.... 
  // each time the loop iterates the nodelist of btn, it assigns the keyword
  // `button` to that iteration of the elements nodelist, so when we click a specific
  // `button` it refers to the button being pressed at that time and not all of them
  button.addEventListener('click', (e) => {
    message[i].style.backgroundColor = 'blue';
  })
})
.container span {
  background: red;
}
<div id='tab1'>

  <div class='container'>
    <span>This was from an include file</span>
    <button>Change color</button>
  </div>

</div>


<div id='tab2'>

  <div class='container'>
    <span>This was from an include file</span>
    <button>Change color</button>
  </div>

</div>

使用 Jquery: 使用 $.each 循环运行列表,并在点击事件上使用 $(this) 并定位前同级元素,即分组的元素在父母 span 标签内配对 (message).

let btn = $('.container button');
let message = $('.container span');


$.each((btn), function(){
  $(this).click(function(){
    $(this).prev().css("background-color", "blue")
  })
})
.container span {
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='tab1'>

  <div class='container'>
    <span>This was from an include file</span>
    <button>Change color</button>
  </div>

</div>


<div id='tab2'>

  <div class='container'>
    <span>This was from an include file</span>
    <button>Change color</button>
  </div>

</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2011-02-22
    • 2016-01-10
    相关资源
    最近更新 更多