【项目实战】基于Vue3+Vant3造一个网页版的类掘金app项目 - 圈子广场

232 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

前言

大家好,在上一篇文章我的圈子中我们已经实现了“我加入的圈子”列表的展示,功能比较简单,只要把样式布局写好然后直接把数据加载上去即可。而我们今天要分享的“圈子广场”共能跟我的圈子非常类似,唯一不同的是在页面的左侧多了个一个分类导航栏,但整体实现起来也是非常简单的,接下来我们就一起分析实现一下。

圈子广场

image.png

  • 圈子列表

    如上图所示,是官方app中的圈子广场截图,我们可以看到该页面主要由三部分组成:顶部搜索栏,左侧分类索引和右侧圈子列表。看一下这个圈子列表是不是跟我们前面分享的我加入的圈子列表几乎一模一样?二话不说直接Ctrl C V了(充分凸显了我们CV工程师的特点,哈哈哈)如果追求代码质量的可以进行一个简单的抽取和封装,而实际工作中也应该要这样,这里为了实现功能就省略这一步了,这样一来我们的工作量直接就减少了一半。接下来我们就可以把精力主要集中在剩下的顶部搜索栏和左侧分类导航栏这两个模块上。

  • 顶部的搜索栏

    当点击搜索框时当前页面中的左侧分类导航及右侧圈子列表会全部隐藏,然后通过输入要查找的圈子名称进行模糊匹配,如果匹配到则直接显示该圈子信息,匹配不到则展示一个空白页面。关于搜索这一块看时间,如果时间充裕我们就实现一下,时间不充足的话也放在后面再实现了。

  • 左侧分类导航栏

    我们今天的分享主要就是集中在分类导航这块。这个左侧导航栏看上去像是一个tab组件,只不过是把每个tab的标题放在了左侧,于是就去vant官方查看了下van-tabs组件,不幸的是这个组件并不支持把tab标题放在左侧。幸运的是又找到另一个替代组件van-sidebar,但是该组件不像tab组件那样包括上面tab标题和下面tab-panel两部分,而是只有左侧标题区域没有右侧的内容区域,但依然能够满足我们的需求,只是需要我们手动添加一个右侧的内容展示区域。 大概实现思路如下:

  • 在topic.vue组件中的圈子广场tab的内容区域中添加van-sidebar组件

  • 在van-sidebar中添加一个van-sidebar-item子组件

  • 定义响应式属性topicCategories,并通过请求官方api(tag_api/v1/query_item_categories)获取到所有的圈子分类填充到topicCategories中

  • 给van-sidebar-item添加v-for指令将所有的圈子分类展示在页面中

  • 再给van-sidebar-item添加click事件,并将圈子分类对应的唯一id作为参数传入,用于加载右侧该分类下对应的圈子数据

  • 剩下的就是把“我的圈子”中关于圈子列表的代码拷贝一份放在圈子广场的右侧区域中,并通过请求官方接口(tag_api/v1/topic/list_by_rec 和 tag_api/v1/topic/list_by_cate_cursor)获取到对应的数据并填充即可 核心代码及效果图如下:

  <div class="topic-square">
    <div class="square-nav">
      <van-sidebar v-model="sideBarIndex">
        <van-sidebar-item title="推荐圈子" @click="lodeTopicsByCate(0)" />
        <van-sidebar-item
          :title="cate.category_name"
          v-for="cate in topicCategories"
          :key="cate.category_id"
          @click="lodeTopicsByCate(cate.category_id)"
        />
      </van-sidebar>
    </div>
    <div class="topic-list">
      <div class="topic-box">
        <div
          class="topic"
          v-for="top in topicListByCate"
          :key="top.topic_id"
        >
          <van-image :src="top.topic.icon" />
          <div class="topic-content">
            <div class="topic-title">{{ top.topic.title }}</div>
            <span class="topic-info"
              >{{ top.topic.follower_count }}掘友·{{
                top.topic.msg_count
              }}沸点</span
            >
          </div>
          <div
            class="topic-join"
            :class="{ 'join-in': !top.user_interact.is_follow }"
          >
            <div class="join" v-if="top.user_interact.is_follow">
              已加入
            </div>
            <div class="join" v-else>加入</div>
          </div>
        </div>
      </div>
    </div>
 </div>
api.queryItemCategories().then((res) => {
      state.topicCategories = res.data;
});

const lodeTopicsByCate = (cate_id) => {
  if (cate_id == 0) {
    api.listByRec().then((res) => {
      state.topicListByCate = res.data;
    });
  } else {
    api.listByCateCursor(cate_id, "0", 30).then((res) => {
      state.topicListByCate = res.data;
    });
  }
};

lodeTopicsByCate(0, 0);

test.gif

总结

本次分享我们实现了圈子广场中的左侧分类和右侧圈子列表的加载功能,还剩下个搜索功能尚未实现,另外上面也提到圈子广场中的部分代码是从我的圈子中拷贝过来的,并且两个圈子都在同一个组件中,因此存在一定的冗余代码,想想还是决定对这部分代码进行抽取和封装一下。所以我们在下次分享中专门实现一下这两个功能点。本次分享就先到这里了。喜欢的小伙伴们帮忙点个赞哦!