【问题标题】:Why does querySelectorAll on text type miss inputs with implicit text type? [duplicate]为什么文本类型上的 querySelectorAll 会错过具有隐式文本类型的输入? [复制]
【发布时间】:2018-11-03 21:16:04
【问题描述】:

我有一个普通的<input> 元素。

我希望document.querySelectorAll('input[type="text"]') 能够(至少)检索到该输入,因为the default input type is text

querySelectorAll 不会返回该输入,除非我明确设置type="text"

我有两个问题:

  1. 为什么 querySelectorAll 会忽略带有隐式 type="text" 的输入?
  2. 是否存在针对隐式类型为 text 的输入的查询,该查询排除了所有类型不是 text 的输入?

这是一个说明问题的示例文档:

var output = document.getElementById('output');

var textInputs = document.querySelectorAll('input[type="text"]');

output.innerText = 'input[type="text"] - ' + textInputs.length + ' elements';

var inputs = document.querySelectorAll('input');

output.innerText += '\ninput - ' + inputs.length + ' elements';

output.innerText += '\n\nFirst input type: ' + inputs[0].type;
#output {
  font-family: monospace;
}
<form>
  <input>
  <input type="text">
  <div id="output"></div>
</form>

这是我的浏览器 (Chrome) 中的 JavaScript 输出:

input[type="text"] - 1 elements
input - 2 elements

First input type: text

【问题讨论】:

  • 因为它是一个属性等于选择器。如果属性不存在,则不等于"text"
  • @不,是的。公平地说,类型 text 默认情况下...似乎这只是我没想到的querySelectorAll 的怪癖。
  • document.querySelectorAll('input:not([type]), input[type=text]')

标签: javascript html css-selectors


【解决方案1】:

属性选择器不考虑无效或缺失值默认值。只有在标记中明确指定了属性时,它们才会匹配。

您仍然可以使用input:not([type]) 来解释缺失值默认值,因为没有type 属性的input 元素通过其缺失值默认值保证为文本输入(除非被脚本改变)。

var output = document.getElementById('output');

var textInputs = document.querySelectorAll('input:not([type]), input[type=text]');

output.innerText = 'input[type="text"] - ' + textInputs.length + ' elements';

var inputs = document.querySelectorAll('input');

output.innerText += '\ninput - ' + inputs.length + ' elements';

output.innerText += '\n\nFirst input type: ' + inputs[0].type;
#output { 
  font-family: monospace; 
}
<form>
    <input>
    <input type="text">
    <input type="number">
    <div id="output"></div>
</form>

【讨论】:

  • 感谢您的澄清。您是否知道有关此行为的任何文档(特别是一般不是 querySelectorAll),并且您是否知道满足问题第 2 部分要求的替代查询?
  • @mac9416:不幸的是,这在 HTML 或 Selectors 规范中都没有说明。我能找到的最接近的是§2.4.3 of W3C HTML5,它将缺失值默认描述为当属性“缺失”或“不存在”时使用的值,the Selectors spec 只是将属性选择器描述为基于属性存在的匹配。您必须从那里连接点。
  • @mac9416:嗯,我没有注意到你建议的编辑。对此感到抱歉。
【解决方案2】:

为什么 querySelectorAll 会忽略带有隐式 type="text" 的输​​入?

由于是隐式的,该属性在元素上不存在,所以属性选择器不匹配。

是否有针对隐式类型为文本的输入的查询,排除所有非文本类型的输入?

匹配根本没有类型属性的元素。

console.log(
  document.querySelectorAll("input[type=text], input:not([type])").length,
  "matching elements"
);
input[type=text],
input:not([type]) {
  background: blue;
}
<ol>
  <li><input></li>
  <li><input type="text"></li>
  <li><input type="number"></li>
</ol>

【讨论】:

    【解决方案3】:

    这里有一些答案:

    1. 正如许多人已经提到的,querySelectorAll 需要明确的类型才能匹配它。

    2. 您可能希望使用 sn-p 中的代码来“过滤”querySelectorAll 的结果。

    第三个答案:
    使用.setAttribute("type", "text") 在没有它的元素上显式添加属性

    // Add 'type="text"' on the ones which don't have it
    document.querySelectorAll('input:not([type])').forEach(function(elm){
      elm.setAttribute("type", "text");
    });
    
    // Output
    var inputs = document.querySelectorAll('input[type="text"]');
    document.getElementById('output').innerText += 'input[type="text"] - ' + inputs.length + ' elements';
    <form><!-- Added other input types -->
      <input>
      <input type="text">
      <input type="number">
      <input type="date">
      <div id="output"></div>
      <script>
      </script>
    </form>

    ⋅ ⋅ ⋅

    第二个答案(其他人更快):
    querySelectorAll 中添加input:not([type])

    var output = document.getElementById('output');
    var inputs = document.querySelectorAll('input[type="text"], input:not([type])');
    
    output.innerText += 'input[type="text"] - ' + inputs.length + ' elements';
    <form><!-- Added other input types -->
      <input>
      <input type="text">
      <input type="number">
      <input type="date">
      <div id="output"></div>
      <script>
      </script>
    </form>

    ⋅ ⋅ ⋅

    第一个答案(不值得):
    使用循环检查querySelectorAll返回的每个元素

    // Variables
    var output = document.getElementById('output');
    var inputs = document.querySelectorAll('input');
    var textInputs = [],
      j = 0;
    
    // Loop
    for (i = 0; i < inputs.length; i++) {
      if (inputs[i].type == 'text') {
        textInputs[j] = inputs[i];
        j++
      }
    }
    
    // Output
    output.innerText = 'input[type="text"] - ' + textInputs.length + ' elements';
    <form><!-- Added other input types -->
      <input>
      <input type="text">
      <input type="number">
      <input type="date">
      <div id="output"></div>
      <script>
      </script>
    </form>

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-22
      • 2014-02-13
      • 2020-10-03
      • 2018-03-06
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      相关资源
      最近更新 更多