加载分页

<template>
<div class="p-con">
<div class="classify">
<div class="c-item" v-for="(item, index) in categories" :key="index">
<p class="i-title">{{ item.cat }}</p>
<div class="i-t-item">
<span :class="{ sactive: curtype == subitem.name }" v-for="(subitem, i) in item.sub.slice(0, 8)" :key="i"
@click="changeType(subitem.name)">{{ subitem.name }}</span>
<el-popover class="drop" placement="bottom" :width="'auto'" trigger="click" v-if="item.sub.length > 8">
<template #reference>
<span>更多</span>
</template>
<div class="more">
<span class="m-item" :class="{ sactive: curtype == more.name }"
v-for="more in item.sub.slice(8, item.sub.length)" :key="more.category" @click="changeType(more.name)">
{{ more.name }}
</span>
</div>
</el-popover>
</div>
</div>
</div>
<div class="list">
<div class="l-head">
<h3>
{{ curtype
}}<svg-icon style="cursor: pointer" color="#ccc" v-if="curtype != '全部'" name="close"
@click="changeType('全部')"></svg-icon>
</h3>
<span :class="{ active: order === 'hot' }" @click="changeorder('hot')">最热</span>
<span :class="{ active: order === 'new' }" @click="changeorder('new')">最新</span>
</div>
<div class="wrapper infinite-list" id="playlist">
<play-list :playlist="plist"></play-list>
<template v-if="loading">
<Loading></Loading>
</template>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import PlayList from '@/components/list/PlayList.vue'
import Loading from '@/components/Loading.vue'
import type { categoryItem, playItem } from '@/types'
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { playlisttype, playlist } from '@/api/search'
import { ElMessage } from 'element-plus'

const route = useRoute()

const router = useRouter()

//当前种类
const curtype = ref('全部')

//最新,最热
const order = ref('hot')

//歌单列表
const plist = ref<playItem[]>([])

const loading = ref(true)

const busy = ref(true)

//歌单请求参数
const params = ref({
order: 'hot',
cat: curtype.value,
limit: 48,
offset: 0
})

//分类列表
let categories = reactive<categoryItem[]>([])

//刷新保留上一次页面情况
onMounted(() => {
if (route.query.type) {
params.value.cat = route.query.type
curtype.value = route.query.type
}
if (route.query.order) {
params.value.order = route.query.order
order.value = route.query.order
}
})

const buildData = (keyData: string, longData: any) => {

var mange: any[] = []
longData.map((item: any) => {
// console.log(keyData)
// console.log(item.category)
if (item.category == keyData) {
mange.push(item)
}
})

// console.log(mange)
return mange

}
//请求分类列表
const gettypelist = async () => {
const res: any = await playlisttype()

if (res.code !== 200) {
ElMessage.error('请求分类情况信息失败!')
return
}
categories.length = 0
// console.log(res.categories,"分类")
// console.log(res.sub,"总类")

var newBUD: never[] = []
for (let key in res.categories) {
if (res.categories.hasOwnProperty(key)) {
console.log(key + " -> " + res.categories[key]);
newBUD.push({
cat: res.categories[key],
sub: buildData(key, res.sub)
})

}

}
categories = newBUD
console.log(newBUD)

return
console.log(res, "总类")
console.log(res.categories, "分类")
for (let k in res.categories) {
console.log(k)
categories.push({
cat: String(res.categories[k]),
//分割分类列表中的小列表
sub: res.sub.filter((subitem: any) => {
return subitem.category == k
})
})
}

console.log(categories)
}

//获取歌曲列表
const getplaylist = async () => {
loading.value = true
const res: any = await playlist(params.value)

plist.value = params.value.offset === 0 ? res.playlists : [...plist.value, ...res.playlists]

//是否还有更多数据请求
busy.value = !res.more
// if (busy.value) {
// window.removeEventListener('scroll', checkposition)
// }
}

//加载更多
const loadmore = () => {
busy.value = true //限制加载请求
params.value.offset = plist.value.length
getplaylist()
}

//判断当前位置 触发加载函数
const checkposition = () => {
if (!busy.value) {
const playelement = document.getElementById('playlist')
const rect = playelement?.getBoundingClientRect() //获取元素大小
if (rect?.bottom <= window.innerHeight + 100) {
loadmore() //距离底部还有100px的时候,进行数据加载
}
}
}

//路由变化
const getType = () => {
curtype.value = route.query.cat ? String(route.query.cat) : curtype.value || '全部'
params.value.cat = curtype.value
}

watch(
() => route.query.cat,
() => {
console.log(route.query.cat)
getType()
}
)

onMounted(() => {
getType()
gettypelist()
getplaylist()
window.addEventListener('scroll', checkposition)
})

//修改种类
const changeType = (t: string) => {
if (curtype.value === t) {
return
} else {
curtype.value = t
params.value.cat = t
router.push({ path: '/playlist', query: { type: t, order: order.value } })
}
}

//修改order
const changeorder = (o: string) => {
if (order.value === o) {
return
} else {
order.value = o
params.value.order = o
router.push({ path: '/playlist', query: { type: curtype.value, order: o } })
}
}

//若请求参数变化
watch([() => params.value.order, () => params.value.cat], () => {
getplaylist()
})

onUnmounted(() => {
window.removeEventListener('scroll', checkposition)
})
</script>

<style scoped lang="scss">
.p-con {
.classify {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
min-height: 100px;

.c-item {
  max-width: calc(20% - 10px);

  .i-title {
    font-size: 25px;
    margin-bottom: 8px;
  }

  .i-t-item {
    display: flex;
    flex-wrap: wrap;
  }
}

}

.list {
.l-head {
display: flex;
margin-bottom: 15px;
height: 30px;

  h3 {
    width: 200px;
    font-size: 30px;
    margin-right: 20px;
  }

  span {
    height: 30px;
    line-height: 30px;
    font-size: 20px;
    position: relative;
    margin-right: 15px;
    overflow: hidden;

    &::after {
      position: absolute;
      content: '';
      left: -100%;
      bottom: 0px;
      height: 5px;
      width: 100%;
      background-color: red;
      border-radius: 4px;
      transition: all 0.3s ease;
    }

    &:hover {
      &::after {
        left: 0;
      }
    }
  }

  .active {
    &::after {
      left: 0;
    }
  }
}

}
}

.more {
display: flex;
flex-wrap: wrap;

span {
font-family: 'myfont';
}
}

span {
cursor: pointer;
display: inline-block;
width: fit-content;
padding: 3px 3px;
margin-bottom: 8px;
font-size: 18px;
text-align: center;
border-radius: 4px;
margin: 2px;
}

.sactive {
color: #fff;
background-color: var(--color-line-height);
}
</style>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、初始Vue-Cli 1. 安装 npm install -g @vue/cli # OR yarn globa...
    野鸽儿阅读 510评论 0 0
  • client,page和screen的区别? clientX,clientY是触摸点相对于viewport视口x,...
    change_22fa阅读 1,730评论 1 1
  • 1.sass/scss和less区别?sass是一种动态样式语言,又称为缩排语法,比css多出好些功能(比如变量、...
    Angel_6c4e阅读 788评论 0 14
  • 基础部分 模版语法 1.computed和watch的区别 计算属性computed :支持缓存,data数据不变...
    王蕾_fd49阅读 615评论 0 0
  • 一、vue router跳转方式 1.this.$router.push() 跳转到不同得url,但这个方法会向h...
    风信子_c9da阅读 511评论 0 0