vue之首页的分类与上拉加载更多

首页的分类

在这里插入图片描述

  • 功能:
    • 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值