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

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

前言

大家好,在上一篇文章圈子广场的分享中我们实现了圈子的分类展示功能。而关于圈子列表的部分代码是我们从“我加入的圈子”中直接复制过来的,也就是说有一部分代码是高度相同(冗余)的,为了追求代码质量还是决定对这部分代码进行抽取和封装, 另外还遗留了一个搜索功能尚未实现,因此我们将利用此次分享专门实现一下这两点功能:

  • 圈子列表部分代码抽取封装
  • 圈子广场中圈子搜索功能实现

列表封装

为了尽可能的减少代码的冗余,最终还是决定将列表两个tab页中的列表部分封装一下,既然是要封装成公用组件,那么就必须要考虑到封装后的组件必须要同时能够满足两个tab页的功能需求。虽然说两个tab页中列表代码是高度相同,但仔细分析下来还是有不同的地方,比如我加入的圈子列表中最后面显示的是三个点(...)点击后会弹出一个popup可以取消加入对应的圈子;而广场中的圈子后面是一个圈子加入状态(加入或已加入)。另外数据源也不能写死应该是动态的,因此封装时需要考虑到这两点。下面来分析一下大概实现思路:

  • 在views下新建一个TopicList.vue文件
  • 将Topic.vue中class为topic-box下的所有代码拷贝到TopicList.vue(并将对应的js和css一同拷贝过来)
  • 定义一个data属性(props)类型为Array 必选,用来接收父组件传过来的数据
  • 定义一个isJoin属性(props)类型为Boolean 默认为true,用于区分是我加入的圈子还是圈子广场
  • 最后在Topic.vue中导入TopicList.vue并使用

核心代码及效果图如下:

<!--TopicList.vue-->
<div class="topic-box">
    <!--省略...-->
     <div class="topic-opt" @click="showPopup" v-if="isJoin">
        <van-icon name="ellipsis" size="20px" />
      </div>
      <div
        v-else
        class="topic-join"
        :class="{ 'join-in': !item.user_interact.is_follow }"
      >
        <div class="join" v-if="item.user_interact.is_follow">已加入</div>
        <div class="join" v-else>加入</div>
      </div>
      <van-popup v-model:show="show" position="bottom">
        <div class="cancel-follow" @click="cancelFollow(item.topic.topic_id)">
          取消加入
        </div>
        <div class="close" @click="closePop">取消</div>
      </van-popup>
</div>
复制代码
 props: {
    data: {
      type: Array,
      required: true,
    },
    isJoin: {
      type: Boolean,
      default: true,
    },
  },
复制代码

test.gif

圈子搜索

在官方的圈子广场中,当点击顶部的搜索栏后并不是立即能输入内容,而是将原来所有的内容全部隐藏,并在页面的最顶部显示一个真正的搜索框和取消按钮,而在这个搜索框中才能够实现真正的搜索功能(如下图),整个流程看上去像是跳到了一个新的页面,但实际上貌似是在同一个页面中的不同盒子切换,为了简单起见我们就用一个弹出层来代替了 Screenshot_20220415_160904_com.daimajia.gold.png 大概思路如下:

  • 在Topic.vue的圈子广场的顶部分别添加一个div盒子和一个van-popup组件
    • div盒子样式设置成一个灰色的文本框样式
    • van-popup充当弹出层角色用于展示真正的搜搜框和搜索结果
  • 在van-popup中添加一个van-field组件,真正的搜索框,用于模糊匹配圈子名称
  • 接着在文本框下面添加我们上面封装好的topic-list组件(又派上用场了)用于展示搜素结果
  • 在setup中请求后端搜索接口:tag_api/v1/topic/list_by_search_cursor,并将文本框输入的内容作为参数传入
  • 最后将搜索结果邦定到topic-list组件上即可

核心代码及效果图:

<div class="topic-search" @click="showSearch">搜索圈子</div>
<van-popup v-model:show="show" position="top" @closed="closePop">
    <div class="search-result">
      <div class="topic-search">
        <van-field
          v-model="search"
          placeholder="搜索圈子"
          @update:model-value="valueChange"
        />
      </div>
      <topic-list :data="topicList" :isJoin="false" />
    </div>
</van-popup>
复制代码
const tabChange = (tab) => {
  if (tab.name === 0) {
    loadMyTopics();
  } else {
    lodeTopicsByCate(0, 0);
  }
};

if (state.active === 0) {
  loadMyTopics();
} else {
  lodeTopicsByCate(0, 0);
}

const showSearch = () => {
  state.show = true;

  state.topicList = [];
};
const valueChange = () => {
  api.listBySearchCursor("0", state.search, 30).then((res) => {
    state.topicList = res.data;
  });
};
const closePop = () => {
  lodeTopicsByCate(0, 0);
    };
复制代码

test.gif

总结

本次分享我们对圈子列表相关代码进行了抽取和封装,实现了代码的重复利用。另外还实现了圈子广场中圈子的模糊搜索功能,整体下来也基本没有什么技术难点。今天的分享就到这里了,欢迎小伙伴点赞关注加评论哦!感谢!

猜你喜欢

转载自juejin.im/post/7086829319124680740