【问题标题】:Can I use duplicate IDs on multiple <template> fragments?我可以在多个 <template> 片段上使用重复的 ID 吗?
【发布时间】:2020-11-29 15:16:44
【问题描述】:

当元素 ID 重复但 &lt;template&gt; 不同时,为什么 HTML5 验证会失败。我打算一次只使用一个模板,这样实际的 DOM ID 就不会重复。

类似:

<template id="companyAccount">
   <li><label>Company: <input type="text" id="account_name"></label></li>
   <li><label>Street: <input id="account_street" ...
   ...
</template>
<template id="residentialAccount">
   <li><label>Name: <input type="text" id="account_name"></label></li>
   <li><label>Street: <input id="account_street" ...
   ...
</template>
<script>
...
let template = $(isResidential ? '#residentialAccount' : '#companyAccount').get(0).content;
$('#account_info').empty().append(template.cloneNode(true));
</script>

【问题讨论】:

  • 发布示例代码。您如何“一次只显示一个”?
  • @TJBlackman - 我添加了一个示例。
  • ID 必须是全局唯一的,这样当它们存在时,它们就只有一个。看起来同一个 ID 有可能在 HTML 文件中出现多次,也许并非总是如此,但即使只是一秒钟,它也会失败。如果您必须使用相同的 ID,则必须 100% 确保在添加另一个之前完全删除一个。但只需使用类或数据属性即可解决问题。
  • 据我所知,每个模板的内容都进入一个单独的文档,因此每个 id 在其文档中都是唯一的,不应该是验证错误。但坦率地说,唯一能回答这个问题的人是sideshowbarker,所以你不妨raise it as an issue on the validator.

标签: html dom xhtml w3c-validation


【解决方案1】:

正如 TJBlackman 提到的每个 valueid 属性必须是唯一的。但是,在使用代码时, 可以确定要导入的代码是否包含重复的id。此外,我几乎已经停止使用验证器,因为它们没有得到很好的维护(而且 W3C 的 CSS 验证器很糟糕),控制台、正确的错误处理和使用 HTML5 的 XML 解析器会告诉你几乎所有你想要的东西需要知道。

您有几个选择。您可以使用data-account="residential"(不要错误地使用camelCasing,因为这最终会使您与标准机构发生直接冲突)并通过document.querySelectorAll检测属性:

function $(o)
{
 var a = true;

 try {document.querySelectorAll(o);}
 catch(err) {a = false; console.log('Error: "'+o+'" is not a valid CSS selector.'); sound.notice();}

 return (a && document.querySelectorAll && document.querySelectorAll(o)) ? document.querySelectorAll(o) : false;
}

用法:$('[data-account="residential"]')[0].length$('[data-account="residential"]')[0].value

或者,您可以使用我的平台做我所做的事情,该平台紧密集成了所有东西,尽管这是我使用的功能,您可能会决定为您的特定目的瘦身。您可以使用document.createTreeWalker 并逐个遍历每个元素以扫描walker.currentNode.hasAttribute('id') 以针对document.getElementById 进行测试。此代码用于将 XML 导入我平台上的 DOM:

/******** part of larger ajax() function ********/

if (xhr.readyState == 4 && xhr.status != 204)
{}

//This code occurs within the above condition.
var r = jax_id_duplication_prevention(xhr.responseXML,param_id_container_pos,id_container);

if (r)
{
 if (param_id_container_pos=='after') {id_container.parentNode.insertBefore(xml.getElementsByTagName('*')[0],id_container.nextSibling);}
 else if (param_id_container_pos=='before') {id_container.parentNode.insertBefore(document.importNode(xml.getElementsByTagName('*')[0],true),id_container);}
 else if (param_id_container_pos=='first')
 {
  if (id_container.childNodes.length > 0) {id_container.insertBefore(document.importNode(xml.getElementsByTagName('*')[0],true),id_container.firstChild);}
  else {id_container.appendChild(document.importNode(xml.getElementsByTagName('*')[0],true));}
 }
 else if (param_id_container_pos=='inside') {id_container.appendChild(document.importNode(xml.getElementsByTagName('*')[0],true));}
 else if (param_id_container_pos=='replace') {id_container.parentNode.replaceChild(document.importNode(xml.getElementsByTagName('*')[0],true),id_container);}
 else if (param_id_container_pos=='fragment')
 {
  if (option.fragment) {delete option.fragment;}
  option.fragment = document.importNode(new DOMParser().parseFromString(xhr.responseText,'application/xml').childNodes[0],true);
  if (id_container && typeof id_container == 'function') {id_container();}
 }
 else {alert('Error: unknown position to import data to: '+id_container_pos);}
}
/******** part of larger ajax() function ********/

function ajax_id_duplication_prevention(xml,param_id_container_pos,id_container)
{
 var re = true;
 if (typeof id_container == 'string' && id_container.length > 0 && id_(id_container)) {id_container = id_(id_container);}

 if (typeof option.id_fade == 'string' && option.id_fade.length > 0 && id_(option.id_fade)) {element_del(option.id_fade); option.id_fade = '';}

 if (typeof xml.firstChild.hasAttribute == 'function')
 {
  if (xml.firstChild.hasAttribute('id') && xml.firstChild.getAttribute('id').length > 0 && id_(xml.firstChild.getAttribute('id')) && id_(xml.firstChild.id).parentNode.id=='liquid') {change(xml.firstChild.id,'fade');}

  if (xml.firstChild.hasAttribute('id') && xml.firstChild.getAttribute('id').length > 0 && id_(xml.firstChild.id) && !id_(xml.firstChild.id).parentNode.id=='liquid') {re = false;}
  else if (typeof document.createTreeWalker=='function')
  {
   var idz = [];
   try
   {
    var walker = document.createTreeWalker(xml,NodeFilter.SHOW_ELEMENT,null,false);

    while (walker.nextNode())
    {
     if (walker.currentNode.hasAttribute('id') && walker.currentNode.getAttribute('id').length > 0)
     {
      if (walker.currentNode.id==undefined && walker.currentNode.nodeName.toLowerCase()=='parsererror') {console.log('Error: a parser error was detected.');}
      else if (walker.currentNode.id==undefined) {alert('walker.currentNode.nodeName = '+walker.currentNode.nodeName+'\n\n'+document.serializeToString(xml));}
      else
      {
       for (var i = 0; i<id_('liquid').childNodes.length; i++)
       {
        if (id_('liquid').childNodes[i].nodeType==1 && id_(walker.currentNode.id) && is_node_parent(walker.currentNode.id,id_('liquid').childNodes[i]) && (param_id_container_pos!='replace' || walker.currentNode.id!=id_container.id))
        {
         if (param_id_container_pos != 'replace' && id_container != walker.currentNode.id) {element_del(id_('liquid').childNodes[i]);}//If changing operator test: ajax('get','?ajax=1&web3_url=/'+url_section()+'/'+url_page(),'replace',push_current_id());
        }
       }

       var n = id_(walker.currentNode.id);
       if (in_array(walker.currentNode.id,idz))
       {
        var fd = new FormData();
        fd.append('ajax','error_xml');
        fd.append('post_error','Duplicate id <code>'+walker.currentNode.id+'</code>.');
        fd.append('post_url',url_window().split(url_base())[1].split('?')[0]);
        fd.append('post_xml',new XMLSerializer().serializeToString(xml));
        if (fd) {ajax('post',path+'/themes/',fd);}

        modal.alert('Error: can not import XML, the id \''+walker.currentNode.id+'\' was detected twice in the layer being imported. Duplicated ID\'s break expected functionality and are illegal. While the XML content was not imported it is still possible that the related request was successful. It is possible to override this problem by simply doing a full request (press the Go button in your browser\'s graphic user interface) however if the id is referenced programmatically the website may exhibit unusual behavior.');
        break;
        setTimeout(function()
        {
         history.back();
         push_reload();
         console.log('Developer: duplicate id '+walker.currentNode.id+' was encounterted.');
         if (status >= 9) {modal.xml('Duplicate ID Error', '%3Cp%3EError%3A%20the%20id%20%3Ccode%3E'+walker.currentNode.id+'%3C%2Fcode%3E%20occurred%20twice%20and%20therefore%20the%20page%20can%20not%20be%20viewed.%3C%2Fp%3E%3Cp%3EFor%20debugging%20and%20fixing%20purposes%20you%20should%20consider%20opening%20the%20URL%20in%20a%20new%20tab.%3C%2Fp%3E%3Cdiv%20class%3D%22center%20margin%22%3E%3Cinput%20onclick%3D%22modal.close()%3B%22%20tabindex%3D%223%22%20type%3D%22button%22%20value%3D%22Close%22%20%2F%3E%3C%2Fdiv%3E');}
         else {modal.xml('Duplicate ID Error', '%3Cp%3EError%3A%20the%20id%20%3Ccode%3E'+walker.currentNode.id+'%3C%2Fcode%3E%20occurred%20twice%20and%20therefore%20the%20page%20can%20not%20be%20viewed.%3C%2Fp%3E%3Cdiv%20class%3D%22center%20margin%22%3E%3Cinput%20onclick%3D%22modal.close()%3B%22%20tabindex%3D%223%22%20type%3D%22button%22%20value%3D%22Close%22%20%2F%3E%3C%2Fdiv%3E');}
         re = false;
        },4000);
       }
       else {idz.push(walker.currentNode.id);}
      }

      if (id_(walker.currentNode.id) && (param_id_container_pos!='replace' && walker.currentNode.id!=id_container.id && !is_node_parent(walker.currentNode.id,id_container)))
      {//ajax replace (carousel loader) complications if changed.
       re = false;
       modal.alert('Error: unable to import page, the id \''+walker.currentNode.id+'\' already exists in the DOM.');
       break;
      }
     }
    }
   }
   catch (err) {}//IE9
  }
 }

 return re;
}

无论您如何解决问题,它不是标准机构解决的问题,必须由开发人员明确处理。未能处理重复的id 属性/值将导致在某些时候选择了错误的元素,随着时间的推移,可能会悄悄地累积受损/格式错误的数据, 内没人会注意到,因此很容易阻碍如果不是彻底破坏由此产生的任何业务关系。祝你好运!

【讨论】:

    猜你喜欢
    • 2020-10-08
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2012-09-26
    • 1970-01-01
    • 2012-06-07
    相关资源
    最近更新 更多