2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
import { withNoopInstall } from '../../utils'
import waterFall from './src/water-fall.vue'
export const TnWaterFall = withNoopInstall(waterFall)
export default TnWaterFall
export * from './src/water-fall'
export type { TnWaterFallInstance } from './src/instance'
@@ -0,0 +1 @@
export * from './use-water-fall'
@@ -0,0 +1,127 @@
import { getCurrentInstance, nextTick, ref, watch } from 'vue'
import { useSelectorQuery } from '../../../../hooks'
import { cloneDeep, debugWarn, generateId } from '../../../../utils'
import type { WaterFallProps } from '../water-fall'
export const useWaterFall = (props: WaterFallProps) => {
const instance = getCurrentInstance()
if (!instance) {
debugWarn('TnWaterFall', '请在 setup 中使用 useWaterFall')
}
const componentId = `twf-${generateId()}`
const { getSelectorNodeInfo } = useSelectorQuery(instance)
// 切割左右两边数据
const leftData = ref<any[]>([])
const rightData = ref<any[]>([])
// 获取左右两边容器的高度信息
let leftContainerHeight = 0
let rightContainerHeight = 0
const getContainerHeight = async () => {
try {
const leftContainerRectInfo = await getSelectorNodeInfo(
`#${componentId}-left`
)
const rightContainerRectInfo = await getSelectorNodeInfo(
`#${componentId}-right`
)
leftContainerHeight = leftContainerRectInfo.height || leftContainerHeight
rightContainerHeight =
rightContainerRectInfo.height || rightContainerHeight
} catch (err) {
debugWarn('TnWaterFall', `获取容器高度信息失败:${err}`)
}
}
// 旧数据
let oldUserData: any[] = []
// 分割数据
const splitData = async (data: any[]) => {
if (!data || !data.length) return
if (props.mode === 'calc') {
// 根据左右两边的数据高度,判断当前数据应该放在左边还是右边
await getContainerHeight()
if (leftContainerHeight <= rightContainerHeight) {
leftData.value.push(data.shift())
} else {
rightData.value.push(data.shift())
}
nextTick(() => {
setTimeout(() => {
splitData(data)
}, 200)
})
} else if (props.mode === 'normal') {
// 判断当前的第一个元素是放在左边还是右边
let firstLeft = true
await getContainerHeight()
if (leftData.value.length > rightData.value.length) {
firstLeft = false
}
let leftSmall = false
if (leftContainerHeight < rightContainerHeight) {
leftSmall = true
}
// 按照顺序,左右交替放置数据
data.forEach((item, index) => {
if ((index % 2 === 0 && firstLeft) || leftSmall) {
leftData.value.push(item)
} else {
rightData.value.push(item)
}
if (!firstLeft) {
firstLeft = true
}
if (leftSmall && index >= 2) {
leftSmall = false
}
})
}
}
// 重新渲染列表
const resetWaterFall = () => {
if (!props.data) return
leftData.value = []
rightData.value = []
leftContainerHeight = 0
rightContainerHeight = 0
nextTick(() => {
oldUserData = props.data
splitData(props.data)
})
}
watch(
() => props.data,
(val) => {
if (!val) return
if (oldUserData.length === val.length) return
const newData = cloneDeep(val.slice(oldUserData.length))
if (!newData.length) {
leftData.value = []
rightData.value = []
leftContainerHeight = 0
rightContainerHeight = 0
}
nextTick(() => {
oldUserData = val
splitData(newData)
})
},
{
immediate: true,
}
)
return {
componentId,
leftData,
rightData,
resetWaterFall,
}
}
@@ -0,0 +1,3 @@
import type WaterFall from './water-fall.vue'
export type TnWaterFallInstance = InstanceType<typeof WaterFall>
@@ -0,0 +1,27 @@
import { buildProps } from '../../../utils'
import type { ExtractPropTypes } from 'vue'
export const waterFallModes = ['normal', 'calc'] as const
export const waterFallProps = buildProps({
/**
* @description 列表数据
*/
data: {
type: Array,
default: () => [],
},
/**
* @description 瀑布流模式
*/
mode: {
type: String,
values: waterFallModes,
default: 'normal',
},
})
export type WaterFallProps = ExtractPropTypes<typeof waterFallProps>
export type WaterFallMode = (typeof waterFallModes)[number]
@@ -0,0 +1,62 @@
<script lang="ts" setup>
import { useNamespace } from '../../../hooks'
import { waterFallProps } from './water-fall'
import { useWaterFall } from './composables'
const props = defineProps(waterFallProps)
const ns = useNamespace('water-fall')
const { componentId, leftData, rightData, resetWaterFall } = useWaterFall(props)
defineExpose({
/**
* @description 重置瀑布流
*/
reset: resetWaterFall,
})
</script>
// #ifdef MP-WEIXIN
<script lang="ts">
export default {
options: {
// 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
virtualHost: true,
},
}
</script>
// #endif
<template>
<view :class="[ns.b()]">
<!-- 左边数据 -->
<view :id="`${componentId}-left`" class="left" :class="[ns.e('container')]">
<view
v-for="(item, index) in leftData"
:key="index"
:class="[ns.e('item')]"
>
<slot name="left" :item="item" :index="index" />
</view>
</view>
<!-- 右边数据 -->
<view
:id="`${componentId}-right`"
class="right"
:class="[ns.e('container')]"
>
<view
v-for="(item, index) in rightData"
:key="index"
:class="[ns.e('item')]"
>
<slot name="right" :item="item" :index="index" />
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
@import '../../../theme-chalk/src/water-fall.scss';
</style>