【终极之战】基于Vue3+Vant3造一个网页版的类掘金app项目 - 个人主页

824 阅读3分钟

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

前言

大家好,上一篇文章创作者中心分享中我们实现了创作者中心的功能。到目前为止,为期2个月的项目实战分享终于是接近了尾声,本篇分享也将是我们本次项目实战分享的最后一篇内容。本次将分享最后一个功能模块 - 个人主页的实现。

布局分析

image.png 第一件事还是布局分析,如上图所示该页面分为3个模块:个人信息模块、徽章模块和内容模块。其中个人信息模块头像信息,用户名,用户等级,所佩戴的徽章以及关注相关的信息和当前掘力值。这些基本信息在我们之前的分享中基本都已经实现过了,所以这块内容实现起来就很简单了。

徽章模块默认展示当前所获得的徽章数并展示出前三个徽章,点击后跳转到徽章墙页面。

第三个模块内容模块就略显复杂了,从上图我们可以看到这个模块中是一组tab页,包括动态、文章、专栏、沸点、收藏、关注和点赞几个模块。其中除了“动态”模块外其他几个模块展示的都是比较专一的内容,比如文章就显示文章列表数据,专栏就展示的是专栏数据,其他几个也是以此类推。而唯一不同的也是比较复杂的就是“动态”模块,因为这个动态中的内容是包含了后面几个模块中所有内容的。也就是说动态模块中的列表内容既有可能是文章数据也可能是沸点数据等等。因此我们本次分享仅实现一个动态中的功能即可。

数据渲染

  • 个人信息/徽章 首先个人信息和徽章两个模块还是使用我们之前分析过的get接口来获取数据,在这个get接口中已经包含了我们想要的个人信息数据和徽章数据。如下图中红框中的obtain_badges就是当前所获取的前5个徽章,以及wear_badges是当前所佩戴的徽章。 image.png
 <div class="profile-box">
    <van-image class="avatar" :src="userInfo.avatar_large" round />
    <div class="title-box">
      <span class="title">{{ userInfo.user_name }}</span>
      <img
        src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/74bd93adef7feff4fee26d08c0845b4f.svg"
        alt="lv-1"
      />
      <img :src="userInfo.badges.wear_badges[0].image_url" class="badge-img" />
      <div class="edit">编辑</div>
    </div>
    <div class="follow-box">
      <div class="follow-item">
        <div class="count">{{ userInfo.followee_count }}</div>
        <div class="tag">关注</div>
      </div>
      <div class="follow-item">
        <div class="count">{{ userInfo.follower_count }}</div>
        <div class="tag">关注者</div>
      </div>
      <div class="follow-item">
        <div class="count">{{ userInfo.power }}</div>
        <div class="tag">掘力值</div>
      </div>
    </div>
  </div>
  <div class="badge-box">
    <div class="badge-left">
      <img
        src="//lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/badge-count-icon.0586ac4.png"
        alt=""
        class="count-icon"
      />
      <div class="badge-count">
        获得的徽章
        <span style="font-weight: bold">{{
          userInfo.badges.obtain_count
        }}</span>
      </div>
    </div>
    <ul class="badge-list" @click="toBadgeWall">
      <li
        class="badge-item"
        v-for="item in userInfo.badges.obtain_badges"
        :key="item.badge_id"
      >
        <img
          :src="item.image_url"
          :alt="item.badge_name"
          class="badge-item-img"
        />
      </li>
      <li>
        <van-icon name="arrow" size="16" />
      </li>
    </ul>
  </div>
api.getUserinfo().then((res) => {
   state.userInfo = res.data;
});
  • 动态 image.png 动态内容中的数据通过一个“dynamic”的接口获取,其中有一个“target_type”字段用于区分当前展示的动态内容是文章还是沸点或者是专栏等其他信息,而target_data则是要渲染的内容数据,所以我们这个动态列表中需要准备多种盒子,然后通过target_type字段值来决定当前数据内容target_data应该渲染到哪个盒子中。
<van-tab title="动态">
    <div v-for="tar in target.list" :key="tar.id">
      <!--关注信息-->
      <div class="follow" v-if="tar.target_type === 'user'">
        <van-image class="avatar" :src="tar.user.avatar_large" round />
        <div class="username">{{ tar.user.user_name }}</div>
        <div class="follow-label">关注了</div>
        <div class="username">{{ tar.target_data.user_name }}</div>
      </div>
      <!--文章信息-->
      <div class="article-list" v-if="tar.target_type === 'article'">
        <div class="header" v-if="tar.action !== 0">
          <span>{{ tar.user.user_name }}</span>
          <span>赞了这篇文章</span>
        </div>
        <!--...-->
      </div>
      <!--沸点信息-->
      <div class="short-msg-list" v-if="tar.target_type === 'short_msg'">
        <div class="header" v-if="tar.action !== 2">
          <span>{{ tar.user.user_name }}</span>
          <span>赞了这篇沸点</span>
        </div>
        <comment
          :avatar_large="tar.target_data.author_user_info.avatar_large"
          :user_name="tar.target_data.author_user_info.user_name"
          :job_title="tar.target_data.author_user_info.job_title"
          :company="tar.target_data.author_user_info.company"
          :ctime="tar.target_data.msg_Info.ctime"
          :origin_content="tar.target_data.msg_Info.content"
          :sub_content="tar.target_data.msg_Info.content"
          :comment_id="tar.target_data.msg_Info.msg_id"
          :pic_list="tar.target_data.msg_Info.pic_list"
        />
      </div>
    </div>
  </van-tab>
api.dynamic().then((res) => {
     state.target = res.data;
});

test.gif

总结

今天的分享实现了本次项目实战中的最后一块内容 - 个人主页。到此关于项目实战的全部分享就暂告一段落了,如果有喜欢的小伙伴欢迎给个赞哦。 最后附上前后端项目地址

前端:github.com/Alvin668/ju…

后端:github.com/Alvin668/ju…