<template>
  <div class="app-scroll-view" ref="scrollElement">
    <slot></slot>
  </div>
</template>

<script lang="ts" setup>
import { ref, onActivated, onDeactivated, watch } from 'vue'

const emit = defineEmits(['update:scrollTop', 'scroll']);

const props = defineProps({
  // 滚动元素名称(用于不同组件缓存滚动条位置)
  scrollName: {
    type: String,
    default: 'default',
  },
  // 滚动条位置
  scrollTop: {
    type: Number,
    default: 0,
  }
})

const scrollElement = ref<HTMLDivElement>();
const scrollMap = new Map<string, number>();

// 监听滚动条位置
const onScroll = (e: Event) => {
  const el = e.target as HTMLDivElement;
  scrollMap.set(props.scrollName, el.scrollTop);
  emit('update:scrollTop', el.scrollTop);
  emit('scroll', el)
}

// 设置滚动条位置
const setScrollTop = (callback?: (el: HTMLDivElement) => void) => {
  const el = scrollElement.value;
  if (el) {
    el.style.setProperty('opacity', '0');
    el.scrollTop = scrollMap.get(props.scrollName) ?? 0;

    window.setTimeout(() => {
      el.style.setProperty('opacity', '1');
      callback && callback(el);
    }, 0)
  }
}

onActivated(() => {
  setScrollTop((el) => {
    el.addEventListener('scroll', onScroll); // 监听滚动条事件
  })
})

onDeactivated(() => {
  const el = scrollElement.value;
  el?.removeEventListener('scroll', onScroll); // 移除滚动条事件
})

watch(() => props.scrollName, () => setScrollTop());
</script>