J'ai un écouteur d'événements qui ressemble à ceci:
window.addEventListener('scroll', scroll.throttle(
triggered,
{state: state, wrapper: wrapper, children: children, scroll: scroll},
50
));
Et j'ai une classe qui ressemble à ceci:
Scroll = class{
constructor(){
this.on = true;
}
throttle(fn, v, wait){
var time = Date.now();
return () => {
if ((time + wait - Date.now()) < 0 && this.on) {
fn(v);
time = Date.now();
}
}
}
triggered(o){
if(o.state.check !== 0){
o.scroll.on = false;
o.wrapper.classList.toggle('flic-down', o.state.check === 1)
o.wrapper.classList.toggle('flic-up', o.state.check === -1)
o.state.update();
o.wrapper.classList.add('flic-transition')
setTimeout(()=>{this.changeDone(o)}, 1200);
}
}
changeDone(o) {
o.wrapper.classList.remove('flic-transition', 'flic-up', 'flic-down');
o.children.setClasses(o.state.state);
o.wrapper.getElementsByClassName('flic-active')[0].scrollIntoView(true);
o.scroll.on = true;
}
},
Je n'aime pas passer l'état, le wrapper, les enfants et le défilement en tant que variables. Je préférerais les stocker en classe lors de leur instanciation. Je comprends que le problème est que "ceci" ne sera pas transmis correctement et qu'il pourra être lié. Mais parce que la fonction d'accélérateur, je ne comprends pas comment passer cela.
3 réponses
Je recommanderais de séparer la limitation du défilement.
class Throttle {
constructor() {
this.on = true;
}
get(fn, wait) {
var time = Date.now();
return (...args) => {
if ((time + wait - Date.now()) < 0 && this.on) {
fn(...args);
time = Date.now();
}
}
}
}
class Scroll {
constructor(state, wrapper, children) {
this.state = state;
this.wrapper = wrapper;
this.children = children;
this.throttle = new Throttle();
}
triggered() {
if (this.state.check !== 0) {
this.throttle.on = false;
this.wrapper.classList.toggle('flic-down', this.state.check === 1)
this.wrapper.classList.toggle('flic-up', this.state.check === -1)
this.state.update();
this.wrapper.classList.add('flic-transition')
setTimeout(()=>{this.changeDone()}, 1200);
}
}
changeDone() {
this.wrapper.classList.remove('flic-transition', 'flic-up', 'flic-down');
this.children.setClasses(this.state.state);
this.wrapper.getElementsByClassName('flic-active')[0].scrollIntoView(true);
this.throttle.on = true;
}
}
Vous feriez alors
const scroll = new Scroll(state, wrapper, children);
window.addEventListener('scroll', scroll.throttle.get(() => scroll.triggered(), 50));
Remarquez la fonction de flèche transmise à throttle.get
qui appelle triggered
sur l'instance scroll
, au lieu de passer la méthode sans contexte.
Si vous voulez les mélanger tous les deux dans la même classe, je ne vois pas pourquoi throttle
prendrait fn
et v
comme paramètres. Vous ne l'utilisez que pour appeler triggered
de toute façon:
class ThrottledScroll {
constructor(state, wrapper, children) {
this.state = state;
this.wrapper = wrapper;
this.children = children;
this.throttle = new Throttle();
this.on = true;
}
get(wait) {
var time = Date.now();
return () => {
if ((time + wait - Date.now()) < 0 && this.on) {
this.triggered();
time = Date.now();
}
}
}
triggered() {
if (this.state.check !== 0) {
this.on = false;
this.wrapper.classList.toggle('flic-down', this.state.check === 1)
this.wrapper.classList.toggle('flic-up', this.state.check === -1)
this.state.update();
this.wrapper.classList.add('flic-transition')
setTimeout(()=>{this.changeDone()}, 1200);
}
}
changeDone() {
this.wrapper.classList.remove('flic-transition', 'flic-up', 'flic-down');
this.children.setClasses(this.state.state);
this.wrapper.getElementsByClassName('flic-active')[0].scrollIntoView(true);
this.on = true;
}
}
Avec
const scroll = new ThrottledScroll(state, wrapper, children);
window.addEventListener('scroll', scroll.get(50));
L'ajout de la liaison au constructeur a fonctionné pour la classe, qui gère le problème de liaison lorsqu'il est appelé hors contexte:
Scroll = class{
constructor(){
this.on = true;
this.triggered = this.triggered.bind(this)
this.changeDone = this.changeDone.bind(this)
}
throttle(fn, v, wait){
var time = Date.now();
return () => {
if ((time + wait - Date.now()) < 0 && this.on) {
fn(v);
time = Date.now();
}
}
}
triggered(o){
if(o.state.check !== 0){
o.scroll.on = false;
o.wrapper.classList.toggle('flic-down', o.state.check === 1)
o.wrapper.classList.toggle('flic-up', o.state.check === -1)
o.state.update();
o.wrapper.classList.add('flic-transition')
setTimeout(()=>{this.changeDone(o)}, 1200);
}
}
changeDone(o) {
o.wrapper.classList.remove('flic-transition', 'flic-up', 'flic-down');
o.children.setClasses(o.state.state);
o.wrapper.getElementsByClassName('flic-active')[0].scrollIntoView(true);
o.scroll.on = true;
}
}
L'auditeur d'événements devait avoir scroll.triggered
contre triggered
à moins que vous ne le déconstruisiez (const { triggered } = scroll
) avant lui et nous n'avons pas vu cela:
window.addEventListener('scroll', scroll.throttle(
scroll.triggered,
{state: state, wrapper: wrapper, children: children, scroll: scroll},
50
))
Dans votre constructeur de classe, vous pouvez lier le contexte de vos méthodes de classe à la classe avec this.methodName = this.methodName.bind(this)
. ReyHaynes a raison, cela peut également être accompli en définissant les méthodes de classe en tant que fonctions fléchées, mais je pense que c'est toujours une fonctionnalité ES7 non confirmée, donc vous ne voudrez peut-être pas l'utiliser.
Si cela n’est pas clair ou n’aide pas, vous trouverez peut-être un contexte utile ici. C'est une ressource React, mais, si je comprends bien, votre problème est traité dans React tout le temps.
Questions connexes
Questions liées
De nouvelles questions
javascript
Pour des questions concernant la programmation dans ECMAScript (JavaScript / JS) et ses divers dialectes / implémentations (hors ActionScript). Veuillez inclure toutes les balises pertinentes dans votre question; par exemple, [node.js], [jquery], [json], etc.