Начинающий Javascript: не удается заставить функцию выполняться на нескольких объектах

#javascript

Вопрос:

Я работаю над Буткампом веб-разработчика Коула Стила на Udemy #264. Бурлящее Событие. Я пытаюсь создать функцию, которая позволит передавать один или несколько объектов и выполнять одно и то же действие (переключить список классов «скрыть», чтобы кнопка «Нажмите здесь, чтобы скрыть» исчезла, и появилась кнопка «Нажмите здесь, чтобы показать») для каждого из них.

Я могу заставить это работать, вызвав функцию отдельно, например

 const container = document.querySelector('#container')
const show = document.querySelector('#show')

function hideOneElement(ele){
    ele.classList.toggle('hide');
}
show.addEventListener('click', function () {
    hideOneElement(container);
    hideOneElement(show);
})
 

Однако, когда я пытаюсь вызвать функцию с обоими контейнерами (div с надписью «Нажмите здесь, чтобы скрыть») и показать одновременно, я не могу заставить ее работать. Я попытался написать функцию скрытия как для…, например

 function hideElements(elements){
   for (const ele of elements) {
   ele.classList.toggle('hide')
   }
}
let stuffToHide = [container,show]
hideElements(stuffToHide)
 

Однако это, похоже, не работает. Я также попытался передать два отдельных аргумента, но это тоже, похоже, не работает:

 function hideElements(ele1, ele2) {
    ele1.classList.toggle('hide');
    ele2.classList.toggle('hide')
}
hideElements(container, show);
 

На данный момент я не уверен, куда идти, и мой Google-джитсу не находит ничего полезного. На самом деле это не является частью упражнения курса, но, похоже, мне в корне не хватает чего-то в вызове функций.

Полный код и HTML ниже:

 <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        .hide {
            display: none;
        }
    </style>
</head>

<body>
    <section onclick="alert('sectopm clicked')">
        <p onclick="alert('paragraph clicked')">I am a paragraph
            <button onclick="alert('button clicked')">Click</button>
        </p>
    </section>


    <div id="container">
        Click to Hide
        <button id="colorbtn">Change Color</button>
    </div>

    <div id="show">
        Click here to Show
    </div>



    <script src="app.js"></script>
</body>

</html>


const makeRandColor = () => {
    const r = Math.floor(Math.random() * 256);
    const g = Math.floor(Math.random() * 256);
    const b = Math.floor(Math.random() * 256);
    return (`rgb(${r},${g},${b})`);
}

const button = document.querySelector('#colorbtn')
const container = document.querySelector('#container')
const show = document.querySelector('#show')

function hideElements(ele1, ele2) {
    // for (const ele of elements) {
    //     ele.classList.toggle('hide')
    // }
    // elements.classList.toggle('hide')
    ele1.classList.toggle('hide');
    ele2.classList.toggle('hide')
}

function hideOneElement(ele){
    ele.classList.toggle('hide');
}

//hideElements(show); //run function once to toggle on the 'hide' class so that this is not shown by default. 
hideElements(show)

button.addEventListener('click', function (e) {
    container.style.backgroundColor = makeRandColor();
    e.stopPropagation();
})

container.addEventListener('click', function () {
    hideElements(container, show);
    //hideElements(container, show); //hide the 'click here to hide' stuff
})

    show.addEventListener('click', function () {
        hideElements(container);
        hideElements(show);

    })


show.addEventListener('click', function () {
    hideOneElement(container);
    hideOneElement(show);
})
 

Ответ №1:

«Я пытаюсь создать функцию, которая позволит передавать один или несколько объектов», поэтому вам нужно иметь возможность вызывать hideElements либо как hideElements(ele1), либо как hideElements(ele1, ele2)?

В этом случае вам нужно будет передать массив по отдельным переменным. Вы были на правильном пути с закомментированным кодом здесь:

 // for (const ele of elements) {
//     ele.classList.toggle('hide')
// }
// elements.classList.toggle('hide')
 

Но вы не пытались передать их в виде массива, и вы не можете перебирать отдельный элемент (есть только один). Если вы заключите свои переменные в массив с помощью [], это должно решить ваши проблемы.

Пример:

 function hideElements(elements) {
  for (const ele of elements) {
    ele.classList.toggle('hide')
  }
}

hideElements([show]); //run function once to toggle on the 'hide' class so that this is not shown by default. 

container.addEventListener('click', function() {
  hideElements([container, show]);
})

show.addEventListener('click', function() {
  hideElements([container, show]);
})
 

Рабочий Пример:

 const makeRandColor = () => {
  const r = Math.floor(Math.random() * 256);
  const g = Math.floor(Math.random() * 256);
  const b = Math.floor(Math.random() * 256);
  return (`rgb(${r},${g},${b})`);
}

const button = document.querySelector('#colorbtn')
const container = document.querySelector('#container')
const show = document.querySelector('#show')

function hideElements(elements) {
  for (const ele of elements) {
    ele.classList.toggle('hide')
  }
}

function hideOneElement(ele) {
  ele.classList.toggle('hide');
}

hideElements([show]); //run function once to toggle on the 'hide' class so that this is not shown by default. 

button.addEventListener('click', function(e) {
  container.style.backgroundColor = makeRandColor();
  e.stopPropagation();
})

container.addEventListener('click', function() {
  hideElements([container, show]);
})

show.addEventListener('click', function() {
  hideElements([container, show]);
}) 
         .hide {
            display: none;
        } 
 <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <section onclick="alert('sectopm clicked')">
        <p onclick="alert('paragraph clicked')">I am a paragraph
            <button onclick="alert('button clicked')">Click</button>
        </p>
    </section>


    <div id="container">
        Click to Hide
        <button id="colorbtn">Change Color</button>
    </div>

    <div id="show">
        Click here to Show
    </div>

    <script src="app.js"></script>
</body>

</html> 

Комментарии:

1. Большое вам спасибо! Массивы-это проклятие моего существования!

Ответ №2:

Некоторые блоки точно не будут работать — поскольку вы вызываете hideElements с одним аргументом — второй аргумент будет неопределенным, и, конечно, в списке неопределенных нет списка классов (вызывает ошибку).

А также это очень сбивает с толку, потому что вы дважды добавляете прослушиватель событий в элемент show..

Скопировано с вашего поста и добавлено комментариев:

 //hideElements(show); //run function once to toggle on the 'hide' class so that this is not shown by default. 
hideElements(show) // - this will error like I said above as elem2 will be undefined..

button.addEventListener('click', function (e) {
    container.style.backgroundColor = makeRandColor();
    e.stopPropagation();
})

container.addEventListener('click', function () {
    hideElements(container, show);
    //hideElements(container, show); //hide the 'click here to hide' stuff
})


//below you make same event listener twice which is very confusing :

    show.addEventListener('click', function () {
        hideElements(container);
        hideElements(show);

    })


show.addEventListener('click', function () {
    hideOneElement(container);
    hideOneElement(show);
})