Невозможно вызвать метод из класса, возможно, проблема в контексте. А как сделать закрепленный размер SlideBox авто? - PullRequest
0 голосов
/ 07 мая 2020

Как вы можете видеть из консоли, он не может вызвать функцию slideDown(), я предполагаю, что это больше похоже на синтаксическую ошибку или контекст, но действительно не знаю, как ее обойти.

И у меня есть бонусная проблема, как вы можете видеть @keyframe height: 200px; НО, если мы изменим размер браузера, 200 пикселей недостаточно для размещения текста, он уже должен иметь высоту около 250 пикселей. Когда я ставлю height: auto, он ВООБЩЕ действует без анимации. Вы знаете, как установить его в зависимости от фактического размера содержимого внутри?

http://jsfiddle.net/cnvx6sd5/1/

console error

JS

window.addEventListener('load', function(){

    class Aq
    {
            constructor()
            {
                    this.asks = document.querySelectorAll('.ask');

                    this.asks.forEach((ask) => ask.addEventListener('click', this.slideToggle));
            }
//      it's related on hiegth !!!
                slideToggle()
            {
                    let answer = this.parentNode.querySelector('.answer');

                    if(getComputedStyle(answer).display == 'none')
                            this.slideDown(answer);
                    else
                            this.slideUp(answer);
            }

            slideDown(answer)
            {
                    let handler = function()
                    {
                            answer.classList.remove('active_end');
                            answer.removeEventListener('animationend', handler);
                    }

                    answer.classList.add('active_start');
                    setTimeout(()=>{ answer.classList.add('active_end')}, 50);
                    answer.addEventListener('animationend', handler);
            }

            slideUp(answer)
            {
                    let handler = function()
                    {
                            answer.classList.remove('active_start');
                            answer.classList.remove('hide_start');
                            answer.addEventListener('animationend', handler);
                    }

                    answer.classList.add('hide_start');
                    answer.addEventListener('animationend', handler);
            }

            slideUpAll()
            {

            }
    }
        new Aq;
})

CSS

html, body{
    margin: 0;
    background: #eee;
}

.faq{
    padding: 30px;
    max-width: 600px;
}

.item{
    margin: 20px 0;
}

.ask{
    font-size: 30px;
    margin-bottom: 10px;
    cursor: pointer;
}

.answer{
    background: #ff0;
    overflow: hidden;
    display: none;
    padding: 0 15px;
}

.active_start{
    display: block;
    height: 0px;
}

.active_end{
    animation: slideDown 1s linear;
    animation-fill-mode: forwards;
}

.hide_start{
    animation: slideUp 1s linear;
    animation-fill-mode: forwards;
}

@keyframes slideDown
{
    0%{
        height: 0;
    }

    100%{
        height: 200px;
    }

}

@keyframes slideUp
{
    0%{
        height: 200px;
    }

    100%{
        height: 0px;
    }

}

HTML

<!doctype html>
<html lang="ru">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>1</title>
        <link href="css/styles.css" rel="stylesheet">
    </head>
    <body>
        <div class="faq">
            <div class="item">
                <div class="ask">0. Вопрос какой-то №1</div>
                <div class="answer">
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
            </div>
            <div class="item">
                <div class="ask">2. Вопрос какой-то №2</div>
                <div class="answer">
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
            </div>
            <div class="item">
                <div class="ask">3. Вопрос какой-то №3</div>
                <div class="answer">
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
            </div>
            <div class="item">
                <div class="ask">4. Вопрос какой-то №4</div>
                <div class="answer">
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
            </div>
            <div class="item">
                <div class="ask">5. Вопрос какой-то №5</div>
                <div class="answer">
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
            </div>
        </div>
        <script src="js/scripts.js"></script>
    </body>
</html>

1 Ответ

1 голос
/ 07 мая 2020

Метод slideDown или slideUp не будет вызываться из-за контекста this. addEventListener связывает значение this с элементом, который он прослушивает. Поэтому вам нужно изменить контекст this на класс Aq.

Вы можете сделать это с помощью метода bind. У каждой функции есть этот метод, который передает значение, которое должно использоваться как значение для this, и создает новую функцию с этим значением. Теперь this может относиться к классу Aq, а не к элементу <div class="ask">.

class Aq {

  constructor() {
    this.asks = document.querySelectorAll('.ask');
    const bindSlideToggle = this.slideToggle.bind(this);
    this.asks.forEach((ask) => ask.addEventListener('click', bindSlideToggle));
  }

  slideToggle() {
    let answer = this.parentNode.querySelector('.answer');
    if (getComputedStyle(answer).display == 'none')
      this.slideDown(answer);
    else
      this.slideUp(answer);
  }

}

Или вы можете использовать publi c поля класса в сочетании со стрелкой функция для постоянной привязки области this к классу. Но это новая функция (в настоящее время находится на экспериментальной стадии) и может не поддерживать в некоторых браузерах.

class Aq {

  constructor() {
    this.asks = document.querySelectorAll('.ask');
    this.asks.forEach((ask) => ask.addEventListener('click', this.slideToggle));
  }

  slideToggle = event => {
    let answer = this.parentNode.querySelector('.answer');
    if (getComputedStyle(answer).display == 'none')
      this.slideDown(answer);
    else
      this.slideUp(answer);
  }

}
...