[英]Converting plain script to js class to allow having multiple instances fails reading props (that exist)
假设我们有这个(工作)脚本,但由于它使用 querySelector 仅适用于第一个实例:
if ( $( '.marquee' ).length ) {
const marquee = document.querySelector( '.marquee__content' );
let lerpScroll = 0;
let lastScrollPos = 0;
const maxSpeed = 20;
function getScrollPercent() {
let h = document.documentElement,
b = document.body,
st = 'scrollTop',
sh = 'scrollHeight';
return (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
}
function isInViewport() {
const rect = marquee.getBoundingClientRect();
const vOffset = marquee.offsetHeight;
const percent = getScrollPercent() * -1;
lerpScroll += (percent - lerpScroll) * 0.06;
marquee.style.transform = `translateX(${lerpScroll * 4}%)`;
// skew
let scrollPos = window.scrollY;
const container = marquee.querySelector( '.marquee__inner' );
getDirection = scrollPos - lastScrollPos;
lastScrollPos = scrollPos;
if (getDirection > maxSpeed) {
getDirection = maxSpeed;
}
if (getDirection < -maxSpeed) {
getDirection = -maxSpeed;
}
container.style.transform = getDirection;
window.requestAnimationFrame(isInViewport);
}
isInViewport();
}
所以我尝试将其转换为 class:
class Marquee {
constructor(el) {
this.marquee = el;
this.maxSpeed = 20;
this.lerpScroll = 0;
this.lastScrollPos = 0;
}
getScrollPercent() {
let h = document.documentElement,
b = document.body,
st = 'scrollTop',
sh = 'scrollHeight';
return (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
}
isInViewport() {
if (this.marquee) { /* <----- this is line 24 */
console.log(this.marquee.offsetHeight);
const vOffset = this.marquee.offsetHeight;
const percent = this.getScrollPercent() * -1;
this.lerpScroll += (percent - this.lerpScroll) * 0.06;
this.marquee.style.transform = `translateX(${this.lerpScroll * 4}%)`;
// skew
let scrollPos = window.scrollY;
const container = this.marquee.querySelector( '.marquee__inner' );
let getDirection = scrollPos - this.lastScrollPos;
this.lastScrollPos = scrollPos;
if (getDirection > this.maxSpeed) {
getDirection = this.maxSpeed;
}
if (getDirection < -this.maxSpeed) {
getDirection = -this.maxSpeed;
}
container.style.transform = getDirection;
window.requestAnimationFrame(this.isInViewport);
}
}
init () {
this.isInViewport();
}
};
并像这样使用它:
if ( document.querySelectorAll( '.marquee' ).length ) {
document.querySelectorAll( '.marquee__content' ).forEach((element) => {
const m = new Marquee(element);
m.init();
})
}
知道我做错了什么吗? 这是一个小提琴https://jsfiddle.net/bkj3ry74/2/
所以问题是它抱怨它无法读取我可以看到console.log的道具
scripts.js?ver=1.0.0:24 Uncaught TypeError: Cannot read properties of undefined (reading 'marquee')
at isInViewport
在这条线上
window.requestAnimationFrame(this.isInViewport);
you are passing the function from the class as a callback function for .requestAnimationFrame
which is fine and dandy, however because you are passing it as a function, in this context it is getting a new this
inside the function. 也许使用匿名箭头 function 会保留this
的上下文,即
window.requestAnimationFrame(() => this.isInViewport());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.