无法从 class 调用方法,可能是上下文问题。以及如何制作 SlideBox auto 的固定尺寸?
Can't call a method from a class, maybe a context issue. And how to make a pinned size of a SlideBox auto?
正如您从控制台中看到的那样,它无法调用函数 slideDown()
,我猜这更像是语法错误或上下文错误,但我真的不知道如何绕过它。
如您所见,我有一个额外的问题 @keyframe height: 200px;
但是如果我们将浏览器的大小调整为 200px 不足以容纳文本,它已经需要大约 250px 的高度。当我放置 height: auto 时,它根本没有动画。你知道如何根据里面内容的实际大小来设置吗?
http://jsfiddle.net/cnvx6sd5/1/
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>
由于this
的上下文,slideDown
或slideUp
方法将不会被调用。 addEventListener
将 this
值绑定到它正在监听的元素。因此,您需要将 this
的上下文更改为 Aq
class.
您可以使用 bind
方法来做到这一点。每个函数都有这个方法,它传递一个应该用作 this
值的值,并使用该值创建一个新函数。现在 this
可以引用 Aq
class 而不是 <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);
}
}
或者您可以将 public class fields 与箭头函数结合使用,以始终将 this
的范围绑定到 class。但他是一项新功能(目前处于实验阶段)并且可能缺乏某些浏览器的支持。
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);
}
}
正如您从控制台中看到的那样,它无法调用函数 slideDown()
,我猜这更像是语法错误或上下文错误,但我真的不知道如何绕过它。
如您所见,我有一个额外的问题 @keyframe height: 200px;
但是如果我们将浏览器的大小调整为 200px 不足以容纳文本,它已经需要大约 250px 的高度。当我放置 height: auto 时,它根本没有动画。你知道如何根据里面内容的实际大小来设置吗?
http://jsfiddle.net/cnvx6sd5/1/
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>
由于this
的上下文,slideDown
或slideUp
方法将不会被调用。 addEventListener
将 this
值绑定到它正在监听的元素。因此,您需要将 this
的上下文更改为 Aq
class.
您可以使用 bind
方法来做到这一点。每个函数都有这个方法,它传递一个应该用作 this
值的值,并使用该值创建一个新函数。现在 this
可以引用 Aq
class 而不是 <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);
}
}
或者您可以将 public class fields 与箭头函数结合使用,以始终将 this
的范围绑定到 class。但他是一项新功能(目前处于实验阶段)并且可能缺乏某些浏览器的支持。
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);
}
}