繁体   English   中英

将纯脚本转换为 js class 以允许拥有多个实例无法读取道具(存在)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM