如何使用 vanilla JS 以单个值查询具有值数组的数据属性?
How to use vanilla JS to query with a single value a data attribute with array of values?
我有一系列的博客文章,其中有一个标签数组作为 data-tags
html 属性,例如 ["foo", "bar", "baz"]
。我想查询 data-tags
数组中包含 foo
的 DOM 元素。
示例标记:
<li data-tags="['foo', 'bar', 'baz']">...</li>
我知道可以查询数据属性是否存储为奇异值,即:
document.querySelectorAll('[data-specifc-tag="foo"]');
甚至可以 select 数组中包含特定值的元素吗?
(仅限 Vanilla JS,请不要 jQuery)
您可以使用 CSS 获取页面上的任何元素。
即
获取具有 href 的元素 [href]
获取数据类型为价格的 div div[data-type=price]
var attributes = ['data-rel','type'];
attributes.forEach((at)=>{
document.querySelectorAll('['+at+']').forEach((element)=>{
element.append('<b>'+at+'</b>');
});
});
<p>Hello</p>
<p data-rel="title">World!</p>
<p type="emoji">:-)</p>
这是针对您的问题的普通 js 解决方案:
const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
if (/foo/.test(post.getAttribute('data-tags'))) {
fooPosts.push(post);
}
});
// output the filtered posts
console.log(fooPosts);
一个班轮选择:
document.querySelectorAll('[data-tags]').forEach(post => /foo/.test(post.getAttribute('data-tags')) && console.log(post));
或拆分:
document.querySelectorAll('[data-tags]').forEach(post =>
/foo/.test(post.getAttribute('data-tags')) && console.log(post));
请注意,如评论中所述,您的 html 标记无效。数据属性不应包含复杂的数据结构,如数组或对象。按照建议,考虑对数组数据执行 .join() 并将其作为字符串输出到属性 [data-tags] 中。为了便于阅读,其中每个值都可以用逗号分隔。
使用有效标记,您的解决方案将略有不同:
const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
if (post.getAttribute('data-tags').indexOf('foo') > -1) {
fooPosts.push(post);
}
});
console.log(fooPosts);
上面的代码也更快,因为它使用 .indexOf() 来过滤 DOM 节点。
这是可重用函数中的上述代码:
const filterNodesByAttr = (attr, tag) => {
let filtered = [];
const items = document.querySelectorAll(`[${attr}]`);
items.forEach(item => {
if (item.getAttribute(attr).indexOf(tag) > -1) {
filtered.push(item);
}
});
return filtered;
};
const fooPosts = filterNodesByAttr('data-tags', 'foo');
console.log(fooPosts);
综上所述,您需要的查询是
document.querySelectorAll('li[data-tags*=\'"foo"\']')
但是您必须确保 html 数组中的每个元素都包含在双引号内。您可以将其更改为单引号,但请务必更新查询。
您可以通过添加更多规则来搜索多个查询
document.querySelectorAll('li[data-tags*=\'"foo"\']'+'[data-tags*=\'"bar"\']')
下面是一个片段,它根据您可能感兴趣的某些值应用这些查询。我确保使用您在问题中提出的相同 html 结构。
编辑:
我又添加了一个函数 queryAll,它允许进行值查询。因此,您可以搜索必须具有多个值的元素。
function entry(search){
var string = '"' + search + '"';
return '[data-tags*=\'' + string + '\']';
}
function queryAll() {
var queries = Array.prototype.slice.call(arguments).map(function(a){
return '[data-tags*=\'' + a + '\']';
});
//example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
return document.querySelectorAll('li'+ queries.join(''));
}
function query(search) {
var string = '"' + search + '"';
//example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
return document.querySelectorAll('li[data-tags*=\'' + string + '\']');
}
query("foo1"); // One li
query("foo"); //Two li's
queryAll("foo1", "bar1"); //one li
queryAll("foo1", "bar1Not"); //nothing
<ul>
<li data-tags='["foo", "bar", "baz"]'>...</li>
<li data-tags='["foo1", "bar1", "baz1"]'>...</li>
<li data-tags='["foo2", "bar2", "baz2"]'>...</li>
<li data-tags='["foo", "bar2", "baz2"]'>...</li>
</ul>
我有一系列的博客文章,其中有一个标签数组作为 data-tags
html 属性,例如 ["foo", "bar", "baz"]
。我想查询 data-tags
数组中包含 foo
的 DOM 元素。
示例标记:
<li data-tags="['foo', 'bar', 'baz']">...</li>
我知道可以查询数据属性是否存储为奇异值,即:
document.querySelectorAll('[data-specifc-tag="foo"]');
甚至可以 select 数组中包含特定值的元素吗?
(仅限 Vanilla JS,请不要 jQuery)
您可以使用 CSS 获取页面上的任何元素。
即
获取具有 href 的元素 [href]
获取数据类型为价格的 div div[data-type=price]
var attributes = ['data-rel','type'];
attributes.forEach((at)=>{
document.querySelectorAll('['+at+']').forEach((element)=>{
element.append('<b>'+at+'</b>');
});
});
<p>Hello</p>
<p data-rel="title">World!</p>
<p type="emoji">:-)</p>
这是针对您的问题的普通 js 解决方案:
const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
if (/foo/.test(post.getAttribute('data-tags'))) {
fooPosts.push(post);
}
});
// output the filtered posts
console.log(fooPosts);
一个班轮选择:
document.querySelectorAll('[data-tags]').forEach(post => /foo/.test(post.getAttribute('data-tags')) && console.log(post));
或拆分:
document.querySelectorAll('[data-tags]').forEach(post =>
/foo/.test(post.getAttribute('data-tags')) && console.log(post));
请注意,如评论中所述,您的 html 标记无效。数据属性不应包含复杂的数据结构,如数组或对象。按照建议,考虑对数组数据执行 .join() 并将其作为字符串输出到属性 [data-tags] 中。为了便于阅读,其中每个值都可以用逗号分隔。
使用有效标记,您的解决方案将略有不同:
const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
if (post.getAttribute('data-tags').indexOf('foo') > -1) {
fooPosts.push(post);
}
});
console.log(fooPosts);
上面的代码也更快,因为它使用 .indexOf() 来过滤 DOM 节点。 这是可重用函数中的上述代码:
const filterNodesByAttr = (attr, tag) => {
let filtered = [];
const items = document.querySelectorAll(`[${attr}]`);
items.forEach(item => {
if (item.getAttribute(attr).indexOf(tag) > -1) {
filtered.push(item);
}
});
return filtered;
};
const fooPosts = filterNodesByAttr('data-tags', 'foo');
console.log(fooPosts);
综上所述,您需要的查询是
document.querySelectorAll('li[data-tags*=\'"foo"\']')
但是您必须确保 html 数组中的每个元素都包含在双引号内。您可以将其更改为单引号,但请务必更新查询。
您可以通过添加更多规则来搜索多个查询
document.querySelectorAll('li[data-tags*=\'"foo"\']'+'[data-tags*=\'"bar"\']')
下面是一个片段,它根据您可能感兴趣的某些值应用这些查询。我确保使用您在问题中提出的相同 html 结构。
编辑:
我又添加了一个函数 queryAll,它允许进行值查询。因此,您可以搜索必须具有多个值的元素。
function entry(search){
var string = '"' + search + '"';
return '[data-tags*=\'' + string + '\']';
}
function queryAll() {
var queries = Array.prototype.slice.call(arguments).map(function(a){
return '[data-tags*=\'' + a + '\']';
});
//example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
return document.querySelectorAll('li'+ queries.join(''));
}
function query(search) {
var string = '"' + search + '"';
//example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
return document.querySelectorAll('li[data-tags*=\'' + string + '\']');
}
query("foo1"); // One li
query("foo"); //Two li's
queryAll("foo1", "bar1"); //one li
queryAll("foo1", "bar1Not"); //nothing
<ul>
<li data-tags='["foo", "bar", "baz"]'>...</li>
<li data-tags='["foo1", "bar1", "baz1"]'>...</li>
<li data-tags='["foo2", "bar2", "baz2"]'>...</li>
<li data-tags='["foo", "bar2", "baz2"]'>...</li>
</ul>