exposure.vue 3.21 KB
<template>
    <div class="exposure" ref="exposure">
        <slot></slot>
    </div>
</template>
<script>
    import _ from 'lodash';
    import yoho from 'yoho';
    import util from 'common/util';

    export default {
        name: 'Exposure',
        props: {
            topClassName: {
                type: String,
                default: 'top-filter'
            }
        },
        data() {
            return {
                viewArea: {
                    top: 0,
                    bottom: 0
                },
                waiting: []
            };
        },
        watch: {
        },
        methods: {
            checkReport() {
                // 顶部区域可能切换显示和隐藏所以动态获取
                const topRect = document.querySelector(`.${this.topClassName}`).getBoundingClientRect();

                // 可见区域顶部距离视口的上边的距离
                this.viewArea.top = topRect.bottom;

                // 可见区域底部距离视口的上边的距离
                this.viewArea.bottom = window.screen.height;

                let children = _.filter(this.$children, child => {
                    return child.$options.name === 'ExposureItem'
                });

                _.each(children, child => {
                    return child.record(this.isVisible(child.$el))
                });
            },
            isVisible($el) {
                const rect = $el.getBoundingClientRect();

                return ((rect.top > this.viewArea.top && rect.top < this.viewArea.bottom) ||
                rect.bottom > this.viewArea.top && rect.bottom < this.viewArea.bottom)
            },
            addIntoWaiting(param) {
                this.waiting.push(param);
            }
        },
        mounted() {
            if (yoho.isYohoBuy) {
                document.addEventListener('visibilitychange', () => {
                    if (!(document.visibilityState === 'visible')) {
                        let children = _.filter(this.$children, child => {
                            return child.$options.name === 'ExposureItem'
                        });

                        _.each(children, child => {
                            child.record(false);
                        });
                    }

                    if (document.visibilityState === 'visible') {
                        this.checkReport();
                    }
                });

                setInterval(() => {
                    this.$scrollEl = window;
                    this.scrollEvent = util.throttle(50, this.checkReport);
                    if (this.$scrollEl) {
                        this.$scrollEl.addEventListener('scroll', this.scrollEvent);
                    }

                    if (this.$children.length) {
                        this.checkReport();
                    }
                }, 500);

                let reportTimer = setInterval(() => {
                    if (!this.$children.length) { return clearInterval(reportTimer); }
                    if (!this.waiting.length) { return }
                    this.$yas.event('YB_SHOW_EVENT', this.waiting);
                    this.waiting = [];
                }, 3000);
            }
        }
    };
</script>
<style>
</style>