Bootstrap

Vue + Vant + Vuex前端缓存实现带搜索和可点选路径的移动端树形选单列表实践(1)

本篇要记录的是一个完整功能里的其中一部分,这个功能需求大致是在移动端给所选分组下的管理员用户留言,管理员用户可在PC端对留言用户进行回复,而这个功能中除了移动端和PC管理端的列表操作,还涉及一个重要的功能模块——带搜索功能的树状结构组织选择器,大概长下图这样:

由于移动端项目之前没有这种功能的存量代码,因此需要从零开始手动实现。下面开始记录实现过程和思路。

目录

分析需求​​​​​​​

具体实现

页面结构搭建

逻辑实现

更新下一级数据

更新上一级数据

更新顶级数据


分析需求

该功能的需求为页面载入后先展示最顶级的分组列表,没有下级分组的列表项不可点击,不显示“>”符号,点击其中一项展示该分组下的分组列表,需覆盖点击之前的列表内容而非采用层级嵌套的形式,并在分组列表顶部展示当前点击的分组路径,点击之前的路径可返回上级分组。

看到这个需求首先能想到的就是树形结构递归数组操作,需要做的就是根据每次点击所选择的分组项,更新当前的数据节点。

具体实现

移动端组件库使用了Vant,基本需求都能满足,组件的具体使用就不做赘述,直接贴代码。

页面结构搭建

本页的结构并不复杂,主要就是搜索框、组织路径,以及展示列表区块

组织选择页
<template>
  <div style="display: flex;height: 100%;flex-direction:column;background: #F5F5F5;overflow-x: hidden"
       :class="backClicked?'slideOutBack':'slideIn'">
    <PageHeader title='选择组织' :themeType="2"/>
    <div class="container">
      <van-search
          placeholder="请输入搜索关键词"
          input-align="center"
          shape="round"
          disabled
          @click="searchOrg"
      />
      <p class="title-tip">请选择要切换的组织</p>
      <!--  下拉刷新容器   -->
      <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
        <div class="org-container">
          <!--   组织路径  -->
          <van-cell class="org-path">
            <span class="org-path-parent" @click="renderTopTree">{
  { $store.state.userInfo.companyName }}</span>
            <span class="org-path-child" v-for="item in orgPath" :key="item.id">
              <van-icon name="arrow"/>
              <span @click="updateTreeData(item,2)">{
  { item.name }}</span>
            </span>
          </van-cell>
          <van-cell v-if="loading">
            <van-loading color="#2A89FF" style="text-align: center"/>
          </van-cell>
          <!--  分组列表  -->
          <van-radio-group id="org-group" :class="transition" v-else v-model="radio" direction="horizontal">
            <van-cell v-for="item in orgTree" :key="item.id" :is-link="isShowLink(item)">
              <template #icon>
                <van-radio @click="bindSelectedItem(item)" checked-color="#ee0a24" :name="item.id"/>
              </template>
              <template #title>
                <p @click="selectOrg(item)">{
  { item.orgFullName }}</p>
              </template>
            </van-cell>
          </van-radio-group>
        </div>
      </van-pull-refresh>
      <confirmBtn class="confirm-button" :selected-org="selectedOrg"/>
    </div>
  </div>
</template>

点击搜索框后跳转至搜索页面,结构于选择页类似,多了搜索建议关键词和搜索结果关键词高亮等。

组织搜索页
<template>
  <div style="background: #F5F5F5;height: 100%;display: flex;flex-direction: column">
    <PageHeader title='搜索' :backFn='backFn' :themeType="2"/>
    <div class="container">
      <van-search
          v-model.trim="searchValue"
          placeholder="请输入搜索关键词"
          shape="round"
          show-action
          @search="searchFn"
          @cancel="cancelFn"
      />
      <p class="title-tip">{
  { searchTip }}</p>
      <div class="org-container" v-if="searchFinish">
        <van-cell class="org-path">
          <span class="org-path-parent" @click="renderTopTree(resetOrgPath)">{
  { companyName }}</span>
          <span v-if="hasBackToTop">
            <span class="org-path-child" v-for="item in orgPath" :key="item.id">
              <van-icon name="arrow"/>
              <span @click="updateTreeData(item,2)">{
  { item.name }}</span>
            </span>
          </span>
          <span v-else>
            <van-icon name="arrow"/>
              <span>_</span>
          </span>
        </van-cell>
        <van-radio-group id="org-group" :class="transition" v-model="radio" direction="horizontal"
                         v-if="orgTree.length>0 && searchFinish">
          <van-cell v-for="item in orgTree" :key="item.id" :is-link="isShowLink(item)"
                    style="display: flex;align-items: center">
            <template #icon>
              <van-radio @click="checkFn(item)" checked-color="#ee0a24" :name="item.id || item.orgCode"/>
            </template>
            <template #title>
              <div @click=&#
;