vue2请看这个
具体看我的码云项目
首先我们引入的是vant3组件
具体怎么引入就不描述了
!<template>
<div class="main">
<!-- loading效果 -->
<div class="header">
<div>
<div @click="popup"><van-icon name="bar-chart-o" size="20px" /></div>
<div>{{ name == "" ? "全部" : typeMap[name] }}</div>
<div></div>
</div>
<div>
<ul>
<li
:class="{ active: index == num }"
@click="btnScroll(item, index)"
v-for="(item, index) in tableList"
:key="index">
{{ typeMap[item] }}
</li>
</ul>
</div>
</div>
<div class="sec">
<ul>
<van-pull-refresh
success-text="刷新成功"
v-model="isLoading"
:head-height="80"
@refresh="onRefresh"
>
<template #loosing>
<img
class="doge"
src="https://fastly.jsdelivr.net/npm/@vant/assets/doge.png"
/>
</template>
<van-list
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<li v-for="(item, index) in mainList" :key="index">
<div>
<span>
<a href="javascript"
><img v-lazy="item.author.avatar_url"
/></a>
</span>
<span>
<span
:class="[
{ ask: item.tab === 'ask' },
{ share: item.tab === 'share' },
{ job: item.tab === 'job' },
{
good: item.tab === 'good',
good: item.tab === 'dev',
top: item.top === true,
},
]"
>
{{ item.top == true ? "置顶" : typeMap[item.tab] }}</span
>
<span>
<p>{{ item.title }}</p>
<p>
<span style="color: #333">{{ item.reply_count }}/</span
>{{ item.visit_count }}
</p>
</span>
</span>
</div>
<div>{{ getLastTimeStr(item.create_at, true) }}</div>
</li>
</van-list>
</van-pull-refresh>
</ul>
</div>
<!-- 是否展示弹出层 -->
<van-popup
v-model:show="isshow"
closeable
close-icon="close"
position="top"
:style="{ width: '100%', height: '20%' }"
>
内容
</van-popup>
</div>
</template>
<script lang='ts'>
import * as api from "@/api/user"; //引入对应的api
import { getLastTimeStr } from "../utils/utils";
import {
reactive,
toRefs,
onBeforeMount,
onMounted,
getCurrentInstance,
} from "vue";
import { useRouter, useRoute } from "vue-router"; //引入路由
export default {
name: "",
setup() {
let router = useRouter(),
route = useRoute();
const { proxy } = getCurrentInstance() as any;
const day = proxy.day;
const data = reactive({
isshow: false, //隐藏弹出层
num: 0, //tab的index
name: "", //tab的item
type: {
//请求接口的入参
page: 1,
tab: "all",
limit: 18,
total: 100, //这个总数是显示数据总数100就不加载刷新了
},
loading: false, //vant中的loading效果
isLoading: false,
finished: false, //加载完成后的效果
mainList: [],
getLastTimeStr(time: string, friendly: boolean) {
return getLastTimeStr(time, friendly);
},
typeMap: {
all: "全部",
ask: "问答",
share: "分享",
job: "招聘",
good: "精华",
dev: "测试",
},
tableList: ["all", "good", "share", "ask", "job", "dev"],
});
const popup = () => {
data.isshow = true;
};
const btnScroll = (item: any, index: number) => {
//打印带参数的加个数据类型
data.num = index;
data.name = item;
data.type.page = 1;//点击的时候默认显示页为1(初始化)
getList();
};
const onRefresh = () => {
setTimeout(() => {
data.isLoading = false;
data.type.page = 1;
getList();
data.loading = false;
}, 800);
};
var time = 0;
const onLoad = () => {
// 如果加载2次的话 要判断初始化进来的时候
// 判断不上拉加载
if (time != 0) {
getList();
}
time++;
};
const getList = () => {
//请求接口数据
let para = {
page: data.type.page,
limit: data.type.limit,
tab: data.name == "" ? "all" : data.name,
};
api
.topics(para)
.then((res: any) => {
setTimeout(() => {
data.mainList =
data.type.page == 1
? res.data.data
: [...data.mainList, ...res.data.data];
data.type.page++;
data.finished = data.mainList.length >= data.type.total;
data.loading = false;
}, 800);
if (data.type.page >= data.type.total) {
data.finished = true;
data.loading = false;
}
})
.catch((err) => {
data.loading = true; //错误loading打开
});
};
onMounted(() => {
getList();
});
const refData = toRefs(data);
return {
...refData,
popup,
btnScroll,
day,
onLoad,
onRefresh,
};
},
};
</script>
<style lang="scss" scoped>
.main {
height: 100vh;
background-color: #f6f6f6;
.header::-webkit-scrollbar,
.sec::-webkit-scrollbar {
display: none;
}
.header {
height: 80px;
line-height: 80px;
display: flex;
flex-direction: column;
> :nth-of-type(1) {
height: 40px;
line-height: 40px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
}
::-webkit-scrollbar {
display: none;
} //去掉滚动样式
> :nth-child(2) {
width: 120%;
overflow-x: scroll;
height: 20px !important;
line-height: 20px;
box-sizing: border-box;
padding: 15px 0;
flex: 1;
ul {
width: 120%;
height: 20px;
box-sizing: border-box;
.active {
background-color: #80bd01;
color: #fff;
padding: 0 5px;
height: 30px;
line-height: 20px;
border-radius: 3px;
box-sizing: border-box;
}
li {
width: auto;
padding: 0 20px;
height: 30px;
float: left;
box-sizing: border-box;
}
}
}
}
.sec {
overflow-y: scroll;
height: calc(100% - 40px);
background-color: white;
.doge {
width: 140px;
height: 72px;
margin-top: 8px;
border-radius: 4px;
}
ul {
height: 50px;
li {
height: 100%;
display: flex;
vertical-align: middle;
justify-content: space-between;
border-bottom: 0.5px solid rgb(231, 225, 225);
padding: 10px 8px 10px 10px;
box-sizing: border-box;
.ask {
color: white;
background: #3498db;
}
.share {
color: white;
background: #1abc9c;
}
.job {
color: white;
background: #3498db;
}
.good {
color: white;
background: #1abc9c;
}
.top {
color: white;
background: #e74c3c;
}
> :nth-of-type(1) {
position: relative;
> :nth-child(1) {
img {
width: 30px;
height: 30px;
}
}
> :nth-child(2) {
margin-left: 10px;
> :nth-of-type(1) {
padding: 2px 3px;
font-size: 13px;
border-radius: 2px;
position: absolute;
top: 0;
}
> :nth-of-type(2) {
display: inline-block;
text-align: left;
margin-left: 40px;
> :nth-child(1) {
width: 220px;
color: #888;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 15px;
}
> :nth-of-type(2) {
font-size: 12px;
margin-top: 5px;
color: #888;
}
}
}
}
> :nth-child(2) {
font-size: 13px;
color: gray;
}
}
}
}
}
</style>