动手吧,vue移动端消息滚动组件

先看效果图:

1、模板部分


        
  • {{ item }}

2、css部分

.v-message-roll {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: opacity 0.2s;
    .v-icon {
        width: 20px;
        height: 20px;
        flex-shrink: 0;
        vertical-align: middle;
        fill: currentColor;
        overflow: hidden;
    }
    .v-content {
        flex: 1;
        width: 0;
        .v-content-list {
            width: 100%;
            overflow-x: auto;
            white-space: nowrap;
            &::-webkit-scrollbar {
                display: none;
            }
            .v-content-item {
                display: inline-block;
                color: #db8412;
            }
        }
    }
}

.fade-sport-enter,
.fade-sport-leave {
    opacity: 0;
}

3、js部分

const SPEED = {
    FAST: 0.6,
    MIDDLE: 0.4,
    SLOW: 0.3,
};
export default {
    data() {
        return {
            visible: true,
            animationFrameTimer: null,
            touchTimeout: null,
            refreshRateTimer: null,
        };
    },

    props: {
        content: [String, Array],
        touchStop: {
            type: Boolean,
            default: false,
        },
        touchStopDuration: {
            type: Number,
            default: 1500,
        },
        showCloseIcon: {
            type: Boolean,
            default: true,
        },
    },

    watch: {
        content: {
            handler() {
                this.reset();
                this.$nextTick(() => {
                    this.init();
                });
            },
            deep: true,
        },
    },

    computed: {
        contentComputed() {
            if (Object.prototype.toString.call(this.content) === "[object Array]") {
                return this.content;
            }
            return [this.content];
        },
    },

    mounted() {
        this.calcScreenRefreshRate().then((rate) => {
            this.screenRefreshRate = rate;
            this.init();
        });
    },

    methods: {
        init() {
            const itemsRef = this.$refs.itemsRef;
            const scrollW = this.$refs.listRef.scrollWidth;
            this.scrollW = scrollW;
            if (itemsRef.length) {
                this.itemsRef = this.$refs.itemsRef;
                this.setInterval();
            }
        },

        reset() {
            this.$refs.listRef.scrollLeft = 0;
            this.cancelAnimationFrame();
        },

        calcScreenRefreshRate() {
            return new Promise((resolve) => {
                let screenRefreshRate = 0;
                const animationFrameFunc = () => {
                    screenRefreshRate += 2;
                    this.refreshRateTimer = window.requestAnimationFrame(animationFrameFunc);
                };
                setTimeout(() => {
                    window.cancelAnimationFrame(animationFrameFunc);
                    resolve(screenRefreshRate);
                }, 500);
                animationFrameFunc();
            });
        },

        setInterval(num) {
            this.animationFrameTimer = window.requestAnimationFrame(() => this.roll(num));
        },

        roll(num = 0) {
            const step = this.calcStep();
            this.itemsRef.forEach((ele) => {
                ele.style.transform = `translateX(-${num}px)`;
            });
            this.animationFrameTimer = window.requestAnimationFrame(() =>
                this.roll(num < this.scrollW ? num + step : 0)
            );
        },

        calcStep() {
            const screenRefreshRate = this.screenRefreshRate;
            let step = 0;
            if (screenRefreshRate < 90) {
                step = SPEED["FAST"];
            } else if (screenRefreshRate < 120) {
                step = SPEED["MIDDLE"];
            } else {
                step = SPEED["SLOW"];
            }
            return step;
        },

        touchstart() {
            if (!this.touchStop) {
                this.$refs.listRef.style.overflow = "hidden";
            } else {
                this.itemsRef.forEach((ele) => {
                    ele.style.transform = `translateX(0)`;
                });
                this.cancelAnimationFrame();
                window.clearTimeout(this.touchTimeout);
            }
        },

        touchend() {
            if (this.touchStop) {
                const scrollLeft = this.$refs.listRef.scrollLeft;
                this.touchTimeout = setTimeout(() => {
                    this.$refs.listRef.scrollLeft = 0;
                    this.setInterval(scrollLeft);
                }, this.touchStopDuration);
            }
        },

        close() {
            this.visible = false;
            this.$emit("close");
            this.cancelAnimationFrame();
        },

        cancelAnimationFrame() {
            window.cancelAnimationFrame(this.animationFrameTimer);
            window.cancelAnimationFrame(this.refreshRateTimer);
        },
    },

    deactivated() {
        this.cancelAnimationFrame();
    },

    beforeDestroy() {
        this.cancelAnimationFrame();
    },
};

4、参数和事件

可以的话,点个赞嘛

## 属性
 
content: 内容。参数类型:string|array
 
touchStop: 触摸是否停止滚动。参数类型:boolean, 默认 false

touchStopDuration: 触摸停止滚动持续时长(ms)。参数类型:number, 默认1500

showCloseIcon:是否显示关闭按钮。参数类型:boolean, 默认 true
 
## 事件
 
close:关闭事件

你可能感兴趣的:(vue.js,前端,组件)