Zbudowałem komponent w Reakcie, który ma aktualizować swój własny styl przy przewijaniu okna, aby stworzyć efekt paralaksy.
Metoda komponentu render
wygląda następująco:
function() {
let style = { transform: 'translateY(0px)' };
window.addEventListener('scroll', (event) => {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
style.transform = 'translateY(' + itemTranslate + 'px)');
});
return (
<div style={style}></div>
);
}
To nie działa, ponieważ React nie wie, że komponent się zmienił i dlatego komponent nie jest ponownie renderowany.
Próbowałem zapisać wartość itemTranslate
w stanie komponentu i wywołać setState
wywołanie zwrotne przewijania. Jednak to sprawia, że przewijanie jest bezużyteczne, ponieważ jest strasznie wolne.
Jakieś sugestie, jak to zrobić?
javascript
reactjs
Alejandro Pérez
źródło
źródło
render
w tym samym wątku) powinny zajmować się tylko logiką związaną z renderowaniem / aktualizowaniem rzeczywistego DOM w React. Zamiast tego, jak pokazano poniżej @AustinGreco, powinieneś użyć podanych metod cyklu życia Reacta, aby utworzyć i usunąć powiązanie zdarzenia. Dzięki temu jest on samowystarczalny wewnątrz składnika i zapewnia brak wycieków, upewniając się, że powiązanie zdarzenia zostanie usunięte, jeśli / kiedy składnik, który go używa, zostanie odmontowany.Odpowiedzi:
Powinieneś związać słuchacza, w
componentDidMount
ten sposób zostanie utworzony tylko raz. Powinieneś być w stanie przechowywać styl w stanie, prawdopodobnie słuchacz był przyczyną problemów z wydajnością.Coś takiego:
źródło
this.handleScroll = this.handleScroll.bind(this)
powiąże to wewnątrzhandleScroll
komponentu zamiast okna.event.target.scrollingElement.scrollTop
Możesz przekazać funkcję do
onScroll
zdarzenia w elemencie React: https://facebook.github.io/react/docs/events.html#ui-eventsInna odpowiedź, która jest podobna: https://stackoverflow.com/a/36207913/1255973
źródło
Moje rozwiązanie do tworzenia responsywnego paska nawigacyjnego (pozycja: „względna”, gdy nie jest przewijana i ustalona podczas przewijania, a nie na górze strony)
Żadnych problemów z wydajnością.
źródło
aby pomóc każdemu, kto zauważył opóźnione zachowanie / problemy z wydajnością podczas korzystania z odpowiedzi Austins i chciałby uzyskać przykład z odniesieniami wymienionymi w komentarzach, oto przykład, którego używałem do przełączania klasy dla ikony przewijania w górę / w dół:
W metodzie renderowania:
W metodzie obsługi:
I dodaj / usuń swoje programy obsługi w taki sam sposób, jak wspomniał Austin:
dokumenty dotyczące referencji .
źródło
this.scrollIcon.className = whatever-you-want
.className
lubclassList
. Poza tym nie potrzebowałemwindow.addEventListener()
: właśnie użyłem ReactaonScroll
i jest tak szybki, o ile nie aktualizujesz właściwości / stanu!Okazało się, że nie mogę pomyślnie dodać detektora zdarzeń, chyba że przekażę prawdę w następujący sposób:
źródło
userCapture
: opcjonalnie. Wartość logiczna, która określa, czy zdarzenie powinno zostać wykonane w fazie przechwytywania, czy w fazie propagacji. Możliwe wartości: true - procedura obsługi zdarzenia jest wykonywana w fazie przechwytywania false - wartość domyślna. Procedura obsługi zdarzenia jest wykonywana w fazie bulgotaniaPrzykład z użyciem classNames , haków React useEffect , useState i styled-jsx :
źródło
z haczykami
źródło
Przykład składnika funkcji z użyciem useEffect:
Uwaga : należy usunąć detektor zdarzeń, zwracając funkcję „czyszczenia” w useEffect. Jeśli tego nie zrobisz, za każdym razem, gdy składnik zostanie zaktualizowany, będziesz mieć dodatkowy odbiornik przewijania okien.
źródło
Jeśli interesuje Cię składnik podrzędny, który przewija się, ten przykład może być pomocny: https://codepen.io/JohnReynolds57/pen/NLNOyO?editors=0011
źródło
Rozwiązałem problem, używając i modyfikując zmienne CSS. W ten sposób nie muszę modyfikować stanu komponentu, który powoduje problemy z wydajnością.
index.css
Navbar.jsx
Navbar.module.css
źródło
Mój zakład tutaj polega na używaniu komponentów funkcji z nowymi hakami do rozwiązania tego problemu, ale zamiast używać
useEffect
jak w poprzednich odpowiedziach, myślę, że poprawna opcja byłabyuseLayoutEffect
z ważnego powodu:Można to znaleźć w dokumentacji Reacta . Jeśli
useEffect
zamiast tego użyjemy i ponownie załadujemy stronę już przewiniętą, scrolled będzie fałszywe, a nasza klasa nie zostanie zastosowana, powodując niepożądane zachowanie.Przykład:
Możliwym rozwiązaniem problemu mogłoby być https://codepen.io/dcalderon/pen/mdJzOYq
źródło
useLayoutEffect
. Próbuję zobaczyć, o czym wspomniałeś.useEffect
w porównaniu zuseLayoutEffect
..Header--scrolled
czasami stosuje klasę, ale 100% razy.Header--scrolledLayout
jest poprawnie stosowane dzięki useLayoutEffect.Oto kolejny przykład za pomocą haków fontAwesomeIcon i Kendo UI React
[! [Screenshot tutaj] [1]] [1]
źródło
Zaktualizuj odpowiedź z React Hooks
Są to dwa haczyki - jeden dla kierunku (góra / dół / brak) i jeden dla aktualnej pozycji
Użyj w ten sposób:
Oto haczyki:
źródło
Aby rozwinąć odpowiedź @ Austina, powinieneś dodać
this.handleScroll = this.handleScroll.bind(this)
do swojego konstruktora:To daje
handleScroll()
dostęp do właściwego zakresu po wywołaniu z detektora zdarzeń.Należy również pamiętać, że nie można wykonać metody
.bind(this)
w metodachaddEventListener
lubremoveEventListener
, ponieważ każda z nich zwróci odwołania do różnych funkcji, a zdarzenie nie zostanie usunięte po odłączeniu komponentu.źródło