charAt 无法处理在 javascript 中动态创建的元素
charAt not working on element created dynamically in javascript
我正在 javascript 中制作名称搜索应用程序。我在 javascript.
中动态创建了所有列表项
当我使用 charAt(0) 时,应用程序无法运行,没有任何显示
我想匹配输入的第一个字符和数组的第一个字符
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `
<li class="names">
${things[i]}
</li>
`
}
ulEl.innerHTML = listItems
}
render(names)
searchInput.addEventListener("keyup", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
console.log(allNamesDOMCollection.textContent)
console.log(allNamesDOMCollection.textContent)
for (let i = 0; i < allNamesDOMCollection.length; i++) {
let currentName = allNamesDOMCollection[i].textContent.toLowerCase().charAt(0);
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
})
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
undefined
是因为 getElementsByClassName
返回的 HTMLCollection
没有 textContent
属性,但因为那只是在你的 console.log
我们基本上可以忽略这一点。
主要问题是列表项的第一个字符是空白字符,因为你如何构建 listItems
字符串,如果你想要第一个,你需要 trim()
文本内容名称的字符。 (或更改构建方式 listItems
。)
我还建议使用 input
事件,而不是 keyup
。
你的搜索输入允许多个字符,但你只使用第一个字符,这似乎很奇怪,但你在评论中确认这就是你想要的,所以我就这样了——但请看结尾如果您愿意,请回答如何进行完全匹配。
查看 ***
条评论:
// *** Add a declaration
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
let ulEl = document.getElementById("ul-el");
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = "";
for (let i = 0; i < things.length; i++) {
listItems += `
<li class="names">
${things[i]}
</li>
`;
}
ulEl.innerHTML = listItems;
}
render(names);
// *** Use `input`, not `keyup`
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
for (let i = 0; i < allNamesDOMCollection.length; i++) {
// *** Remove the whitespace before getting first character
let currentName = allNamesDOMCollection[i].textContent.trim().toLowerCase().charAt(0);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
});
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
或者,更改构建方式 listItems
:
function render(things) {
let listItems = "";
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`; // *** Remove whitespace around name
}
ulEl.innerHTML = listItems;
}
Live Copy:
// *** Add a declaration
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
let ulEl = document.getElementById("ul-el");
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`; // *** Remove whitespace around name
}
ulEl.innerHTML = listItems;
}
render(names);
// *** Use `input`, not `keyup`
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
for (let i = 0; i < allNamesDOMCollection.length; i++) {
let currentName = allNamesDOMCollection[i].textContent.toLowerCase().charAt(0);
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
});
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
一些其他的旁注。在处理自然语言文本时,一般来说最好是:
优先选择 toLocaleLowerCase()
(和 toLocaleUpperCase()
)而非特定于语言环境的版本。
使用normalize()
(in environments where it's supported) to normalize any sequences of combining characters, etc., so you aren't hit by false negatives because the same glyph (ç
, for instance) is written in different ways (ç
[the "c-cedilla" code point, U+00E7] and ç
[a c
followed by a cedilla/cédille combining mark (U+0327],例如,它们看起来几乎相同但不是相同的代码点序列)。例如,如果您不进行规范化,并且用户使用单个代码点输入 Franç
(例如),则如果用 c
和组合标记:
let input = `Franç`;
let name = "François";
console.log(name.includes(input)); // false
input = input.normalize();
name = name.normalize();
console.log(name.includes(input)); // true
在评论中,您询问如果您确实想要根据整个名称检查整个输入,您会更改什么。为此,如果要匹配名称中的任何位置,只需删除两个 .charAt(0)
调用即可。如果只想匹配名称的开头,请使用 startsWith
而不是 includes
.
这是上面的,使用:
includes
匹配名称中的任意位置
toLocaleLowerCase
和 normalize
for-of
(ES2015+) 而不是 for
因为它更方便
- a class 而不是内联样式来隐藏名称
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
const ulEl = document.getElementById("ul-el");
const searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = "";
for (const thing of things) {
listItems += `
<li class="names">
${thing}
</li>
`;
}
ulEl.innerHTML = listItems;
}
render(names);
function prepForCompare(str) {
str = str.trim().toLocaleLowerCase();
// `normalize` is newer than most of the rest of what we're using
if (str.normalize) {
str = str.normalize();
}
return str;
}
searchInput.addEventListener("input", function(event) {
const searchQuery = prepForCompare(event.target.value);
const allNamesDOMCollection = document.getElementsByClassName("names");
for (const li of allNamesDOMCollection) {
const currentName = prepForCompare(li.textContent);
li.classList.toggle("hidden", !currentName.includes(searchQuery));
}
});
.hidden {
display: none;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
我用 forEach
替换了 for 循环,因为你试图做的是对每个元素应用相同的代码行(几乎是 forEach
所做的)。
您的代码不适用于多个字符,因为您只比较第一个字符。删除两个 charAt(0)
,它应该可以正常工作。
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`
}
ulEl.innerHTML = listItems;
}
render(names)
searchInput.addEventListener("keyup", function(event) {
let searchQuery = event.target.value.toLowerCase();
let allNamesDOMCollection = document.querySelectorAll('.names');
allNamesDOMCollection.forEach(e => {
let currentName = e.innerText.toLowerCase();
if (searchQuery == "") {
e.style.display = "block";
} else if (currentName.includes(searchQuery)) {
e.style.display = "block";
} else {
e.style.display = "none";
}
})
})
body {
margin: 0;
background: #A1FFCE;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #FAFFD1, #A1FFCE);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #FAFFD1, #A1FFCE);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
font-family: 'Roboto', sans-serif;
}
h1 {
color: #363635;
text-align: center;
letter-spacing: 2px;
font-size: 3rem;
}
.container {
width: 600px;
margin: 0 auto;
}
.cont-modifier {
height: 550px;
overflow: auto;
}
input[type=text] {
width: 100%;
box-sizing: border-box;
border: 2px solid #595A4A;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 40px;
background-image: url('search-line.png');
background-position: 10px 10px;
background-repeat: no-repeat;
}
ul {
margin: 0;
padding: 0;
}
.names {
list-style: none;
border-bottom: 3px solid #0b1354;
margin: 3px;
padding: 20px;
font-size: 20px;
font-weight: 300;
letter-spacing: 2px;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
如果你想 'strict' 检查(例如:目前,输入 'A' 也会显示 'Kaira'、'Bilal' 等),你可以在其中添加另一个条件将检查第一个字符是否匹配。
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`
}
ulEl.innerHTML = listItems;
}
render(names)
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase();
let allNamesDOMCollection = document.querySelectorAll('.names');
allNamesDOMCollection.forEach(e => {
let currentName = e.innerText.toLowerCase();
if (searchQuery == "") {
e.style.display = "block";
} else if (currentName.includes(searchQuery) && currentName[0] === searchQuery[0]) {
e.style.display = "block";
} else {
e.style.display = "none";
}
})
})
body {
margin: 0;
background: #A1FFCE;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #FAFFD1, #A1FFCE);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #FAFFD1, #A1FFCE);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
font-family: 'Roboto', sans-serif;
}
h1 {
color: #363635;
text-align: center;
letter-spacing: 2px;
font-size: 3rem;
}
.container {
width: 600px;
margin: 0 auto;
}
.cont-modifier {
height: 550px;
overflow: auto;
}
input[type=text] {
width: 100%;
box-sizing: border-box;
border: 2px solid #595A4A;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 40px;
background-image: url('search-line.png');
background-position: 10px 10px;
background-repeat: no-repeat;
}
ul {
margin: 0;
padding: 0;
}
.names {
list-style: none;
border-bottom: 3px solid #0b1354;
margin: 3px;
padding: 20px;
font-size: 20px;
font-weight: 300;
letter-spacing: 2px;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
我正在 javascript 中制作名称搜索应用程序。我在 javascript.
中动态创建了所有列表项当我使用 charAt(0) 时,应用程序无法运行,没有任何显示 我想匹配输入的第一个字符和数组的第一个字符
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `
<li class="names">
${things[i]}
</li>
`
}
ulEl.innerHTML = listItems
}
render(names)
searchInput.addEventListener("keyup", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
console.log(allNamesDOMCollection.textContent)
console.log(allNamesDOMCollection.textContent)
for (let i = 0; i < allNamesDOMCollection.length; i++) {
let currentName = allNamesDOMCollection[i].textContent.toLowerCase().charAt(0);
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
})
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
undefined
是因为 getElementsByClassName
返回的 HTMLCollection
没有 textContent
属性,但因为那只是在你的 console.log
我们基本上可以忽略这一点。
主要问题是列表项的第一个字符是空白字符,因为你如何构建 listItems
字符串,如果你想要第一个,你需要 trim()
文本内容名称的字符。 (或更改构建方式 listItems
。)
我还建议使用 input
事件,而不是 keyup
。
你的搜索输入允许多个字符,但你只使用第一个字符,这似乎很奇怪,但你在评论中确认这就是你想要的,所以我就这样了——但请看结尾如果您愿意,请回答如何进行完全匹配。
查看 ***
条评论:
// *** Add a declaration
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
let ulEl = document.getElementById("ul-el");
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = "";
for (let i = 0; i < things.length; i++) {
listItems += `
<li class="names">
${things[i]}
</li>
`;
}
ulEl.innerHTML = listItems;
}
render(names);
// *** Use `input`, not `keyup`
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
for (let i = 0; i < allNamesDOMCollection.length; i++) {
// *** Remove the whitespace before getting first character
let currentName = allNamesDOMCollection[i].textContent.trim().toLowerCase().charAt(0);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
});
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
或者,更改构建方式 listItems
:
function render(things) {
let listItems = "";
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`; // *** Remove whitespace around name
}
ulEl.innerHTML = listItems;
}
Live Copy:
// *** Add a declaration
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
let ulEl = document.getElementById("ul-el");
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`; // *** Remove whitespace around name
}
ulEl.innerHTML = listItems;
}
render(names);
// *** Use `input`, not `keyup`
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase().charAt(0);
let allNamesDOMCollection = document.getElementsByClassName('names');
for (let i = 0; i < allNamesDOMCollection.length; i++) {
let currentName = allNamesDOMCollection[i].textContent.toLowerCase().charAt(0);
if (currentName.includes(searchQuery)) {
allNamesDOMCollection[i].style.display = "block";
} else {
allNamesDOMCollection[i].style.display = "none";
}
}
});
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
一些其他的旁注。在处理自然语言文本时,一般来说最好是:
优先选择
toLocaleLowerCase()
(和toLocaleUpperCase()
)而非特定于语言环境的版本。使用
normalize()
(in environments where it's supported) to normalize any sequences of combining characters, etc., so you aren't hit by false negatives because the same glyph (ç
, for instance) is written in different ways (ç
[the "c-cedilla" code point, U+00E7] andç
[ac
followed by a cedilla/cédille combining mark (U+0327],例如,它们看起来几乎相同但不是相同的代码点序列)。例如,如果您不进行规范化,并且用户使用单个代码点输入Franç
(例如),则如果用c
和组合标记:
let input = `Franç`;
let name = "François";
console.log(name.includes(input)); // false
input = input.normalize();
name = name.normalize();
console.log(name.includes(input)); // true
在评论中,您询问如果您确实想要根据整个名称检查整个输入,您会更改什么。为此,如果要匹配名称中的任何位置,只需删除两个 .charAt(0)
调用即可。如果只想匹配名称的开头,请使用 startsWith
而不是 includes
.
这是上面的,使用:
includes
匹配名称中的任意位置toLocaleLowerCase
和normalize
for-of
(ES2015+) 而不是for
因为它更方便- a class 而不是内联样式来隐藏名称
const names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"];
const ulEl = document.getElementById("ul-el");
const searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = "";
for (const thing of things) {
listItems += `
<li class="names">
${thing}
</li>
`;
}
ulEl.innerHTML = listItems;
}
render(names);
function prepForCompare(str) {
str = str.trim().toLocaleLowerCase();
// `normalize` is newer than most of the rest of what we're using
if (str.normalize) {
str = str.normalize();
}
return str;
}
searchInput.addEventListener("input", function(event) {
const searchQuery = prepForCompare(event.target.value);
const allNamesDOMCollection = document.getElementsByClassName("names");
for (const li of allNamesDOMCollection) {
const currentName = prepForCompare(li.textContent);
li.classList.toggle("hidden", !currentName.includes(searchQuery));
}
});
.hidden {
display: none;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
我用 forEach
替换了 for 循环,因为你试图做的是对每个元素应用相同的代码行(几乎是 forEach
所做的)。
您的代码不适用于多个字符,因为您只比较第一个字符。删除两个 charAt(0)
,它应该可以正常工作。
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`
}
ulEl.innerHTML = listItems;
}
render(names)
searchInput.addEventListener("keyup", function(event) {
let searchQuery = event.target.value.toLowerCase();
let allNamesDOMCollection = document.querySelectorAll('.names');
allNamesDOMCollection.forEach(e => {
let currentName = e.innerText.toLowerCase();
if (searchQuery == "") {
e.style.display = "block";
} else if (currentName.includes(searchQuery)) {
e.style.display = "block";
} else {
e.style.display = "none";
}
})
})
body {
margin: 0;
background: #A1FFCE;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #FAFFD1, #A1FFCE);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #FAFFD1, #A1FFCE);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
font-family: 'Roboto', sans-serif;
}
h1 {
color: #363635;
text-align: center;
letter-spacing: 2px;
font-size: 3rem;
}
.container {
width: 600px;
margin: 0 auto;
}
.cont-modifier {
height: 550px;
overflow: auto;
}
input[type=text] {
width: 100%;
box-sizing: border-box;
border: 2px solid #595A4A;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 40px;
background-image: url('search-line.png');
background-position: 10px 10px;
background-repeat: no-repeat;
}
ul {
margin: 0;
padding: 0;
}
.names {
list-style: none;
border-bottom: 3px solid #0b1354;
margin: 3px;
padding: 20px;
font-size: 20px;
font-weight: 300;
letter-spacing: 2px;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>
如果你想 'strict' 检查(例如:目前,输入 'A' 也会显示 'Kaira'、'Bilal' 等),你可以在其中添加另一个条件将检查第一个字符是否匹配。
names = ["Ayesha", "Alina", "Bilal", "Kaira", "Per", "Henry", "Liba", "Rimsha"]
let ulEl = document.getElementById("ul-el")
let searchInput = document.getElementById("searchInput");
function render(things) {
let listItems = ""
for (let i = 0; i < things.length; i++) {
listItems += `<li class="names">${things[i]}</li>`
}
ulEl.innerHTML = listItems;
}
render(names)
searchInput.addEventListener("input", function(event) {
let searchQuery = event.target.value.toLowerCase();
let allNamesDOMCollection = document.querySelectorAll('.names');
allNamesDOMCollection.forEach(e => {
let currentName = e.innerText.toLowerCase();
if (searchQuery == "") {
e.style.display = "block";
} else if (currentName.includes(searchQuery) && currentName[0] === searchQuery[0]) {
e.style.display = "block";
} else {
e.style.display = "none";
}
})
})
body {
margin: 0;
background: #A1FFCE;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #FAFFD1, #A1FFCE);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #FAFFD1, #A1FFCE);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
font-family: 'Roboto', sans-serif;
}
h1 {
color: #363635;
text-align: center;
letter-spacing: 2px;
font-size: 3rem;
}
.container {
width: 600px;
margin: 0 auto;
}
.cont-modifier {
height: 550px;
overflow: auto;
}
input[type=text] {
width: 100%;
box-sizing: border-box;
border: 2px solid #595A4A;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 40px;
background-image: url('search-line.png');
background-position: 10px 10px;
background-repeat: no-repeat;
}
ul {
margin: 0;
padding: 0;
}
.names {
list-style: none;
border-bottom: 3px solid #0b1354;
margin: 3px;
padding: 20px;
font-size: 20px;
font-weight: 300;
letter-spacing: 2px;
}
<h1>Search Names</h1>
<div class="container">
<input type="text" id="searchInput" placeholder="Search">
</div>
<div class="container cont-modifier">
<ul id="ul-el"></ul>
</div>