首页的分类
- 功能:
- 1:一开始先获取到 tab 菜单的数据
- 001 然后定义一个方法,对里面的 tab 中的 item每一项数据操作,添加list(数据),还有page等
- 002 然后获取每一项 根据当前item的id 发起请求 获取到item的数据 用于渲染数据
- 003 002之中需要 拿到 当前 tab中的item选中的 拿到当前item,也就是需要点击的时候,监听active的变化去实现的!
- 2:上拉加载更多
- 001:先拿到 当前item 然后对当前item的page+=1,最后调用更新数据
- 3:点击跳转到详情页
Home.vue
<template>
<div class="home" v-if="category">
<nav-bar></nav-bar>
<div class="categorytab">
<div class="category-ico" @click="$router.push('/editcategory')">
<van-icon name="setting-o" />
</div>
<van-tabs v-model="active" swipeable sticky animated>
<van-tab v-for="(item,index) in category" :key="index" :title="item.title">
<!-- 列表组件
v-model 是否处于加载状态 finished 是否已加载完成 @load="onLoad" 加载事件
immediate-check 是否在初始化时立即执行滚动位置检查
-->
<van-list
v-model="item.loading"
:immediate-check="false"
:finished="item.finished"
finished-text="我也是有底线的"
@load="onLoad"
>
<div class="detailparent">
<!-- 引用子组件 先子组件传递 数据 用于渲染 -->
<artical-detail
class="detailitem"
:detailitem="categoryitem"
v-for="(categoryitem,categoryindex) in item.list"
:key="categoryindex"
@click="gotoArtical(categoryitem.id)"
/>
</div>
</van-list>
</van-tab>
</van-tabs>
</div>
</div>
</template>
<script>
import NavBar from "@/components/comtent/NavBar.vue";
import ArticalDetail from "@/components/comtent/ArticalDetail";
export default {
data() {
return {
category: [],
active: 0
};
},
components: {
NavBar,
ArticalDetail
},
//使用 keep-alive 保存活性
activated() {
if (localStorage.getItem("newCat")) {
let newCat = JSON.parse(localStorage.getItem("newCat"));
this.category = this.changeCategory(newCat);
this.selectArticle();
}
},
methods: {
//00 获取到 tab 菜单选项
async selectCategory() {
if (localStorage.getItem("newCat")) {
return;
}
const res = await this.$request.get("/category");
this.category = this.changeCategory(res.data); //对每一项 菜单item项数据的 操作后 赋值给 这个tab菜单数组
this.selectArticle(); //调用选中的 当前item项 所发起的id 请求回来的数据
},
//01 对 tab中的 每一项 item进行操作
changeCategory(data) {
const category1 = data.map(item => {
item.list = []; // 每一项的 数据
item.page = 0;
item.pagesize = 10;
item.finished = false;
item.loading = true;
return item;
});
return category1;
},
//02 操作tab中选中的item数据 这是对 选中的 item中 拿到当前的id 发起请求 把数据 给 item.list
async selectArticle() {
const categoryitem = this.categoryItem(); // 拿到当前选中的 tab中的item 以id发起请求
const res = await this.$request.get("/detail/" + categoryitem._id, {
params: {
page: categoryitem.page,
pagesize: categoryitem.pagesize
}
});
//往 当前item中的list 推入数据 并且设置 底部加载不可以加载
categoryitem.list.push(...res.data);
categoryitem.loading = false;
//当 返回的数据 小于 请求的10条数据 等 就显示没有更多数据了
if (res.data.length < categoryitem.pagesize) {
categoryitem.finished = true; //加载完成后
}
},
// 03 这是根据 当前 tab中的item选中的 拿到当前item
categoryItem() {
const categoryitem = this.category[this.active];
return categoryitem;
},
//04 上拉 加载更多
onLoad() {
const categoryitem = this.categoryItem(); //先拿到当前的 item 项 然后page += 1 最后调用 selectArticle 更新数据
setTimeout(() => {
categoryitem.page += 1;
this.selectArticle();
}, 1000);
},
//跳转到详情页
gotoArtical(id) {
this.$route.push("/article/", {
params: {
id
}
});
}
},
watch: {
//监听 active的 变化 tab中的选中状态
active() {
const categoryitem = this.categoryItem();
if (!categoryitem.list.length) {
this.selectArticle();
}
}
},
created() {
this.selectCategory();
}
};
</script>
<style lang="scss">
.home {
background-color: white;
}
.detailparent {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.detailitem {
margin: 1.389vw 0;
width: 45%;
}
}
.categorytab {
position: relative;
.category-ico {
position: absolute;
z-index: 5;
right: 0;
top: 1.944vw;
padding: 1.389vw 2.778vw;
background-color: white;
}
}
</style>
ArticalDetail.vue
- 功能:
- 1:接受父组件 传递的数据 渲染页面
- 2: 就是当前的路径 不等于 需要跳转的路径的时候 给跳转
<template>
<div @click="pathPush" v-if="detailitem">
<div class="detailItem">
<div class="imgparent">
<img :src="detailitem.img" alt style="width:100%;height:27.778vw;" />
<div class="bottom">
<div class="icon-play2">
<span class="video">1233</span>
</div>
<div class="icon-file-text">
<span class="comment">{{!detailitem.commentlen ? 66 : detailitem.commentlen}}</span>
</div>
</div>
</div>
<p>{{detailitem.name}}</p>
</div>
</div>
</template>
<script>
export default {
props: ["detailitem"],
methods: {
pathPush() {
//就是当前的路径 不等于 需要跳转的路径的时候 给跳转
if (this.$route.path != `/article/${this.detailitem.id}`) {
this.$router.push(`/article/${this.detailitem.id}`);
}
}
}
};
</script>
<style scoped lang="scss">
.detailItem {
p {
font-size: 3.333vw;
padding: 0.833vw 0;
}
.imgparent {
position: relative;
.bottom {
padding: 0 2.778vw;
margin-bottom: 1.389vw;
position: absolute;
bottom: 0.556vw;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.85), transparent);
justify-content: space-between;
color: white;
display: flex;
left: 0;
right: 0;
}
}
}
</style>
NavBar.vue
<template>
<div class="NavBar">
<div>
<img src="@/assets/logo.png" alt @click="$router.push('/')" />
</div>
<div>
<div>
<van-icon name="search" class="iconNav" />
</div>
</div>
<div>
<img :src="imgUrl" alt @click="$router.push('/userinfo')" v-if="imgUrl" />
<img src="@/assets/default_img.jpg" alt @click="$router.push('/login')" v-else />
<div>下载App</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
imgUrl: ""
};
},
methods: {
async NavInit() {
if (localStorage.getItem("token")) {
const res = await this.$request.get(
"/user/" + localStorage.getItem("id")
);
this.imgUrl = res.data[0].user_img;
}
}
},
mounted() {
this.NavInit();
}
};
</script>
<style scoped lang="scss">
.NavBar {
height: 13.056vw;
display: flex;
background-color: white;
div:nth-child(1) {
width: 25vw;
display: flex;
justify-content: center;
align-items: center;
img {
width: 100%;
}
}
div:nth-child(2) {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 0 1.389vw;
div {
background-color: #f4f4f4;
height: 6.667vw;
width: 100%;
border-radius: 3.333vw;
position: relative;
.iconNav {
color: #aaa;
position: absolute;
left: 2.778vw;
top: 50%;
transform: translate(0, -50%);
}
}
}
div:nth-child(3) {
display: flex;
justify-content: center;
align-items: center;
> div {
margin: 0 2.778vw;
font-size: 3.611vw;
background-color: #fb7299;
padding: 1.389vw 2.778vw;
text-align: center;
border-radius: 0.833vw;
color: white;
}
img {
width: 6.944vw;
height: 6.944vw;
}
}
}
</style>