douyin/src/pages/slideHooks/VInfinite.vue
2023-01-21 03:52:50 +08:00

155 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="jsx">
import {onMounted, reactive, ref, watch, createApp} from "vue";
import GM from '../../utils'
import {getSlideDistance, slideInit, slideReset, slideTouchEnd, slideTouchMove, slideTouchStart} from "./common";
import {SlideType} from "../../utils/const_var";
import SlideItem from './SlideItem'
const props = defineProps({
index: {
type: Number,
default: () => {
return 0
}
},
prefix: {
type: String,
default: () => ''
},
render: {
type: Function,
default: () => {
return null
}
},
list: {
type: Array,
default: () => {
return []
}
},
virtualTotal: {
type: Number,
default: () => 5
},
})
const emit = defineEmits(['update:index'])
const appInsMap = new Map()
const judgeValue = 20
const wrapperEl = ref(null)
const state = reactive({
name: 'SlideVerticalInfinite',
localIndex: props.index,
needCheck: true,
next: false,
start: {x: 0, y: 0, time: 0},
move: {x: 0, y: 0},
wrapper: {width: 0, height: 0, childrenLength: 0}
})
watch(
() => props.index,
(newVal) => {
if (state.localIndex !== newVal) {
state.localIndex = newVal
GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`)
GM.$setCss(wrapperEl.value, 'transform', `translate3d(0,${getSlideDistance(state, SlideType.VERTICAL)}px, 0)`)
}
}
)
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL)
insertContent()
})
//默认使用this.list,刷新时考虑到vue可能更新外面的videos到this.list数据没有那么快因为我要立即刷新
function insertContent(list = props.list) {
let start = 0
let that = this
if (state.localIndex >= (props.virtualTotal - 1) / 2) {
start = state.localIndex - (props.virtualTotal - 1) / 2
}
let end = start + 5
if (end >= list.length) {
end = list.length
start = end - 5
}
if (start < 0) start = 0
// console.log('start', start)
// console.log('end', end)
list.slice(start, end).map(
(item, index) => {
//自动播放当前条可能是0可能是其他试了下用jq来找元素然后trigger play事件要慢点样
let el = getInsEl(item, start + index, start + index === state.localIndex)
wrapperEl.value.appendChild(el)
}
)
GM.$setCss(wrapperEl.value, 'transform', `translate3d(0px,
${-state.localIndex * state.wrapper.height}px, 0px)`)
if (state.localIndex > 2 && list.length > 5) {
$(wrapperEl.value).find(".slide-item").each(function () {
if ((list.length - state.localIndex) > 2) {
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
} else {
$(this).css('top', start * state.wrapper.height)
}
})
}
state.wrapper.childrenLength = wrapperEl.value.children.length
}
function getInsEl(item, index, play = false) {
// console.log('index',index,play)
let slideVNode = props.render(item, index, play, props.prefix)
const app = createApp({
render() {
return <SlideItem>{slideVNode}</SlideItem>
// return slideVNode
}
})
const parent = document.createElement('div')
const ins = app.mount(parent)
appInsMap.set(index, app)
// this.appInsMap.set(index, ins)
return ins.$el
}
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
function touchMove(e) {
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext, SlideType.VERTICAL)
}
function touchEnd(e) {
slideTouchEnd(e, state, canNext, () => {
}, SlideType.VERTICAL)
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) {
return !((state.localIndex === 0 && !isNext) || (state.localIndex === state.wrapper.childrenLength - 1 && isNext));
}
</script>
<template>
<div class="slide">
<div class="slide-list flex-direction-column"
ref="wrapperEl"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
>
<slot></slot>
</div>
</div>
</template>