VideoFeed.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <template>
  2. <SlideVertical
  3. v-model:index="currentIndex"
  4. class="video-feed"
  5. name="home-feed"
  6. >
  7. <SlideItem
  8. v-for="(item, index) in list"
  9. :key="item.aweme_id"
  10. class="feed-item"
  11. >
  12. <BaseVideo
  13. :item="item"
  14. :index="index"
  15. :position="{ uniqueId: UNIQUE_ID, index }"
  16. :is-play="active && currentIndex === index"
  17. @update:item="(val) => onItemUpdate(index, val)"
  18. />
  19. </SlideItem>
  20. </SlideVertical>
  21. </template>
  22. <script setup lang="ts">
  23. import { onMounted, onUnmounted, ref, watch } from 'vue'
  24. import SlideVertical from '@/components/slide/SlideVertical.vue'
  25. import SlideItem from '@/components/slide/SlideItem.vue'
  26. import BaseVideo from '@/components/video/BaseVideo.vue'
  27. import { recommendVideos, type RecommendVideo } from '@/mock/homeData'
  28. import bus, { EVENT_KEY } from '@/utils/bus'
  29. const UNIQUE_ID = 'home'
  30. const props = defineProps({
  31. active: { type: Boolean, default: false },
  32. })
  33. const list = ref<RecommendVideo[]>([...recommendVideos])
  34. const currentIndex = ref(0)
  35. function onItemUpdate(index: number, val: unknown) {
  36. list.value[index] = val as RecommendVideo
  37. }
  38. function onUpdateItem(val?: unknown) {
  39. const payload = val as {
  40. position?: { uniqueId: string; index: number }
  41. item?: RecommendVideo
  42. }
  43. if (payload?.position?.uniqueId === UNIQUE_ID && payload.item) {
  44. list.value[payload.position.index] = payload.item
  45. }
  46. }
  47. function broadcastPlay(index: number) {
  48. bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
  49. uniqueId: UNIQUE_ID,
  50. index,
  51. type: EVENT_KEY.ITEM_PLAY,
  52. })
  53. }
  54. function broadcastStop(index: number) {
  55. bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
  56. uniqueId: UNIQUE_ID,
  57. index,
  58. type: EVENT_KEY.ITEM_STOP,
  59. })
  60. }
  61. function togglePlay() {
  62. if (!props.active) return
  63. bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
  64. uniqueId: UNIQUE_ID,
  65. index: currentIndex.value,
  66. type: EVENT_KEY.ITEM_TOGGLE,
  67. })
  68. }
  69. watch(currentIndex, (newVal, oldVal) => {
  70. if (!props.active) return
  71. bus.emit(EVENT_KEY.CURRENT_ITEM, list.value[newVal])
  72. broadcastPlay(newVal)
  73. if (oldVal !== undefined && oldVal !== newVal) {
  74. setTimeout(() => broadcastStop(oldVal), 200)
  75. }
  76. })
  77. watch(
  78. () => props.active,
  79. (newVal) => {
  80. const t = newVal ? 0 : 200
  81. if (newVal) {
  82. bus.emit(EVENT_KEY.CURRENT_ITEM, list.value[currentIndex.value])
  83. }
  84. setTimeout(() => {
  85. if (newVal) broadcastPlay(currentIndex.value)
  86. else broadcastStop(currentIndex.value)
  87. }, t)
  88. },
  89. { immediate: true },
  90. )
  91. onMounted(() => {
  92. bus.on(EVENT_KEY.TOGGLE_CURRENT_VIDEO, togglePlay)
  93. bus.on(EVENT_KEY.UPDATE_ITEM, onUpdateItem)
  94. })
  95. onUnmounted(() => {
  96. bus.off(EVENT_KEY.TOGGLE_CURRENT_VIDEO, togglePlay)
  97. bus.off(EVENT_KEY.UPDATE_ITEM, onUpdateItem)
  98. })
  99. </script>
  100. <style scoped lang="less">
  101. .video-feed {
  102. height: 100%;
  103. width: 100%;
  104. background: #000;
  105. :deep(.feed-item) {
  106. position: relative;
  107. height: 100%;
  108. width: 100%;
  109. }
  110. }
  111. </style>