нажмите на элемент списка, он включает и выключает линейный класс sytle - PullRequest
0 голосов
/ 12 апреля 2020

я хочу знать, почему я не могу использовать элемент li в функции. то есть я пробовал эту команду li.classList.toggle("done"), но она показывает Uncaught TypeError: Cannot read property 'toggle' of undefined"

var li = document.getElementsByTagName("li");
for(var i=0; i<li.length; i++)
{
	li[i].addEventListener("click", function()
	{
		li.classList.toggle("done");
	});
}
.done {
  text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
	<title>Javascript + DOM</title>
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
	<h1>Shopping List</h1>
	<p id="first">Get it done today</p>
	<input id="userinput" type="text" placeholder="enter items">
	<button id="enter">Enter</button>
	<ul>
		<li class="bold red" random="23">Notebook</li>
		<li>Jello</li>
		<li>Spinach</li>
		<li>Rice</li>
		<li>Birthday Cake</li>
		<li>Candles</li>
	</ul>
	<script type="text/javascript" src="script.js"></script>
</body>
</html>

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Это потому, что li относится к HTMLCollection <li> элементов, а не отдельного элемента <li>. Вам необходимо:

  1. использовать li[i].classList и
  2. использовать let в течение l oop, из-за JS closure

Итак, у вас есть что-то вроде этого, при условии, что вы поддерживаете только браузеры, поддерживающие ES6:

const li = document.getElementsByTagName("li");
for (let i = 0; i < li.length; i++) {
  const el = li[i];
  el.addEventListener("click", () => {
    el.classList.toggle("done");
  });
}

В противном случае вам нужно будет использовать forEach функция вместо Поскольку getElementsByTagName не возвращает итератор, вам лучше использовать querySelectorAll, для чего доступен метод forEach:

var li = document.querySelectorAll('li');
li.forEach(function(el) {
  el.addEventListener("click", function () {
    el.classList.toggle("done");
  });
});

См. Пример проверки концепции:

const li = document.getElementsByTagName("li");
for (let i = 0; i < li.length; i++) {
  li[i].addEventListener("click", function() {
    li[i].classList.toggle("done");
  });
}
.done {
  text-decoration: line-through;
}
<h1>Shopping List</h1>
<p id="first">Get it done today</p>
<input id="userinput" type="text" placeholder="enter items">
<button id="enter">Enter</button>
<ul>
  <li class="bold red" random="23">Notebook</li>
  <li>Jello</li>
  <li>Spinach</li>
  <li>Rice</li>
  <li>Birthday Cake</li>
  <li>Candles</li>
</ul>
0 голосов
/ 12 апреля 2020

Проблема в том, что внутри анонимного function вы находитесь вне области действия по сравнению с исходным for l oop, поскольку код в функции выполняется на click, даже если он не связан с l oop, который его создал.

Вы можете заметить, что li.classList должно было быть li[i].classList, но это не поможет.

Есть несколько способов решить эту проблему, но наиболее я считаю, что надежный способ - использовать данные обратного вызова event и использовать свойство target.

const li = document.getElementsByTagName('li');

for(let i=0; i<li.length; i++)
{
	li[i].addEventListener("click", function(event) {

		event.target.classList.toggle('done');

	});
}
.done {
  text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
	<title>Javascript + DOM</title>
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
	<h1>Shopping List</h1>
	<p id="first">Get it done today</p>
	<input id="userinput" type="text" placeholder="enter items">
	<button id="enter">Enter</button>
	<ul>
		<li class="bold red" random="23">Notebook</li>
		<li>Jello</li>
		<li>Spinach</li>
		<li>Rice</li>
		<li><span>Birthday Cake</span></li>
		<li><div>Candles</div></li>
	</ul>
	<script type="text/javascript" src="script.js"></script>
</body>
</html>

Я добавил несколько дочерних элементов в некоторые элементы списка, чтобы продемонстрировать, что target - это li, а не элемент, по которому щелкнули внутри .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...