【问题标题】:The best way to target DOM定位 DOM 的最佳方式
【发布时间】:2015-12-18 16:19:28
【问题描述】:

我是一名前端开发人员,我担心以我的 DOM 为目标的最佳方式。

让我们想象一个微小的形式来创建一个新的僵尸:

<h1>Add a new zombie</h1>
<form id="create-zombie">
  <input id="zombie" type="text" name="zombie" />
  <input id="lvl" type="text" name="lvl" />
  <button type="submit">Add</button>
</form>

...如果我想获取zombielvl 的值,我将编写如下代码:

class Zombie_Add extends Controller 

  # Dom References
  el: 
    'form': '#create-zombie'
    'zombie': '#zombie'
    'lvl': '#lvl'

  run: ->

    @on 'submit', @el.form, @validate

  validate: (e) =>

    e.preventDefault()

    zombie = $(@el.zombie).val()
    lvl = $(@el.lvl).val()

module.exports = Zombie_Add

“没问题”,它可以完成这项工作,但我对那个“结构”有一些问题:

  1. 如果有人触摸了 DOM 并删除了一个 ID,我就完蛋了,它会破坏我的代码(Captain Obvious 发现了!)

  2. 对于更复杂的选择器,它只是一团糟(我正在考虑类似[name^="dummy-"] input:first 的东西)。我想不难想象el 的名字有多糟糕。

无论如何,我今天想学习的是从 JS 定位 DOM 的最佳方法是什么。使用 ID、class 值或data-* 属性更好吗?我们如何用简单的英语等美化选择器......

【问题讨论】:

  • 视情况而定。我通常会尝试通过使用模板/渲染来避免将 dom 元素全部定位在一起,这意味着我只需要定位一个元素,即视图需要插入的元素。
  • 我不是在谈论单页应用程序^^
  • 单页应用程序并不是唯一受益于基于视图的渲染的应用程序。

标签: javascript jquery dom coffeescript


【解决方案1】:

如果有人触摸了 DOM 并删除了一个 ID,我就完蛋了,它 破坏了我的密码(Captain Obvious 发现了!)

在 DOM 中定位单个唯一元素的最佳方法是使用 ID,就像使用 zombielvl 一样。它执行速度快,编码简单。

如果有人弄乱了你 HTML 中的 id 值,那将会破坏你的 Javascript。就是那样子。任何弄乱您的 HTML 的人都必须足够聪明,才能知道 ID 值的存在是有原因的,因此如果他们想更改或删除它,那么他们有责任找到可以在 Javascript 中进行相应更改的人。就是这样。

对于更复杂的选择器,只是一团糟(我在想 一些类似的东西 [name^="dummy-"] 输入:第一)。我想这很容易 想象一下 el 的名字有多牛逼。

对于更复杂的选择器也是如此。不管你喜不喜欢,现代网页是服务器端内容、演示 HTML 和 Javascript 的融合。三者必须共同努力以提供最终解决方案。虽然您努力通过良好的设计技术和实践来避免不必要的依赖关系,但您无法避免所有依赖关系,甚至试图避免所有可能的依赖关系也不是一种有效的开发方式。

示例

有一些编码实践可以使您的代码对 HTML 的编辑不那么敏感,我认为这些实践是可取的。例如,考虑这个 HTML sn-p:

<div class="header">
    <div class="headerBorder">
        <div class="actions>
            <a href="#" class="hide">Hide</a>
        </div>
        <div class="contentContainer">
            <div class="content">
            ... content here
            </div>
         </div>
     </div>
</div>
<div class="header">
    ... more of these repeated
</div>

并且您希望有这样的代码,当您单击“隐藏”链接时,它会隐藏内容。

如果你这样编码:

$(".header .actions .hide").click(function() {
    $(this).parent().next().children().first().hide();
});

然后,您在 Javascript 中嵌入了一些关于按钮和内容区域的 HTML 结构的非常详细的知识,以及对该 HTML 的几乎所有结构更改(甚至只是添加了一层 div 以帮助进行一些布局) 将破坏 Javascript。这很糟糕。

相反,您可以这样写:

$(".header .actions .hide").click(function() {
    $(this).closest(".header").find(".content").hide();
});

这仅取决于一个 HTML 结构概念 - 对应于 .hide 按钮的 .content 位于公共 .header 父元素中的某个位置。可以更改 .header 父级中的整个结构,并且此代码不会中断。这是一个健壮的代码,它试图尽可能独立于 HTML 结构的细节。

不管怎样,我今天想学习的是最好的瞄准方法 来自 JS 的 DOM。使用 ID、类值或 data-* 更好吗? 属性?我们如何用简单的英语等美化选择器......

最好使用 ID 来定位页面中只有一个唯一元素的元素。

最好使用类名来定位页面中可能有多个元素的元素,如果您只想定位具有类名的特定项目,则可以将其与选择器的其他部分结合使用。

数据属性可以在选择器中使用,但这并不是它们的主要用途。我想不出任何理由为什么使用数据属性而不是类名会更好。我使用数据属性来存储脚本将使用的对象上的实际数据。这往往会让代码更通用,让内容自我描述。

当您谈论删除类以更改元素的状态时,这是对类的合法使用,但使用与添加/删除相同的类来选择元素只是一个糟糕的设计决定状态。为这两个目的使用不同的类名。例如,您可以有一个名为“selected”的类名来指示选择状态,但如果您只需要选定的对象,则只能在选择器中使用它。如果您想要一个表格中的所有订单项,则不会使用“.selected”,而是为该对象创建一个更具描述性的类名称,例如“lineitem”。请记住,您可以在一个对象上拥有多个类名,因此您可以在同一个对象上为不同的目的使用不同的类名。

您似乎在这里寻找一些神奇的子弹,以防止 HTML 中的更改以任何方式影响 Javascript。那根本不存在。选择一个 DOM 元素或找到一个与被点击的东西相关的 DOM 元素将依赖于一些关于 HTML 是如何结构化或标记的固有知识。重要的是,您要尽量减少对所需内容的依赖,并且任何搞乱 HTML 的人都了解如何最好地改变事物而不破坏 Javascript 或与了解 Javascript 的人讨论更改。如果您在项目的不同部分使用不同的技能/人员,他们必须协调他们的努力,以免破坏事情或了解与系统其他部分的依赖关系。就是那样子。这里没有什么神奇的答案可以消除 HTML 和 Javascript 之间的所有依赖关系。智能设计具有更小、更明显的依赖关系。糟糕的设计具有大量且通常隐藏的依赖关系。

您关于“简单英语”的问题对我来说并不是特别清楚。使用描述性的 ID 名称、类名称或属性名称似乎很明显,这使得读者可以清楚地看到该特定名称的用途。我不确定你在寻找什么。

【讨论】:

  • 这是有道理的,但它被另一个坏习惯完全破坏了:选择类(它们经常改变,你可以删除元素的当前类“状态”的类,等等......)。如果我在您的示例中使用 ID,它也会中断,因为根据定义,ID 是唯一的。所以这就是我从一开始的问题,我如何才能更好地定位 DOM(使用 data-x 属性?)
  • @JeremieGes - 根据您的最后评论,我在答案末尾添加了更多内容。你似乎在这里寻找灵丹妙药 - 没有。您使用良好的设计实践来减少 HTML 和 JS 之间的依赖关系并使它们更加明显。没有消除依赖这样的事情。
  • 这是一个完美的答案,你得到了我想说的。所以我的结论可能是以这种方式为类添加前缀“.js-example”以引起项目中另一个开发人员的注意。很高兴得到你的帮助;)
猜你喜欢
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2010-09-08
  • 2018-05-18
相关资源
最近更新 更多