纵横研究院VU...

vue手写列表多级联动

2019-12-15  本文已影响0人  北风吹_yfy

一、项目需求

用户登录后展示条件筛选页面,多层条件筛选,存在单选和多选情况,以及视图样式根据选中情况有相应的变,点击清空按钮后恢复初始状态。效果图如下: 20191215_163317.gif

二、数据分析

列表渲染的数据部分前端写死,部分是从后端接口调取:

// 获取接口数据
mounted () {
    let param = {
      enableFlag: 'Y',
    }
    let promise0 = fetchCarBrand(param)
    let promise1 = fetchSelectTList('APP.CAR.ENERGY_TYPE')
    let promise2 = fetchSelectTList('APP.CAR.DISPLACEMENT')
    let promise3 = fetchSelectTList('APP.CAR.CLOUR')
    let promise4 = fetchSelectTList('APP.CAR.PASSENGERS')
    Promise.all([promise0, promise1, promise2, promise3, promise4]).then(
      res => {
        console.log(res)
        this.carBrandData = res[0].rows
        this.newCarBrandData = this.carBrandData.map(item => {
          return Object.assign(item, { isPiont: false })
        })
        this.energyType = res[1].rows
        this.displacement = res[2].rows
        this.carColor = res[3].rows
        this.persons = res[4].rows
      }
    )
}
(1)三级联动---以车辆品牌为例: image.png
<!-- 一层列表 -->
<li
    :class="{ switch: activeIndex === 1 }"
    class="car-model"
    @click="handleSwitchLiTwo"
  >
    <div
      :class="{
        bluecolor: selectParam.brandList || selectParam.modelList
      }"
    >
      <i
        :class="{
          bluepoint: selectParam.brandList || selectParam.modelList
        }"
      />车辆品牌
    </div>
    <!-- 二层列表 -->
    <ul v-if="isModelShow">
      <li
        v-for="(item, index) in newCarBrandData"
        :key="index"
        @click="selectCarModel(item)"
      >
        <div
          :class="{
            bluecolor:
              selectParam.brandList &&
              selectParam.brandList.find(e => e === item.brandId)
          }"
        >
          <i
            :class="{
              bluepoint: modelMap[item.brandId] && modelMap[item.brandId].length
            }"
          />
          {{ item.brandName }}
        </div>
      </li>
    </ul>
   <!-- 三层列表 -->
    <ul v-if="isModel" class="car-model-child">
      <li
        v-for="(v, i) in newModelData"
        :key="i"
        :class="{
          bluecolor:
            modelMap[v.brandId] && modelMap[v.brandId].includes(v.modelId)
        }"
        @click.stop="handleSelectModel(v)"
      >
        {{ v.modelName }}
      </li>
    </ul>
  </li>

此处将二层列表和三层列表写成并列结构,原本写的是嵌套结构,但由于后来属性控制出现问题,改成了并列结构。
同时针对动态类名的控制这里使用的是我点击选中后生成的条件列表数组去控制,如果用boolean值就会有一堆的变量需要在不同阶段去改变,很繁琐。
首先一层列表的切换通过判断当前点击下标是否等于该元素在列表中的下标相等,来控制状态。关于tab切换操作方法可参考vue写tab切换

// 品牌选择
    selectCarModel (item) {
      this.isModel = true
      // 判断筛选参数里是否存在该列表属性,若没有给一个初始空数组
      if (!this.selectParam.brandList) this.selectParam.brandList = []
     // 若存在则先判断是首次点击选中还是要再次点击取消
      if (this.selectParam.brandList.indexOf(item.brandId) > -1) {
        // 再次点击取消操作
        this.newModelData = []  // 清空第三层列表
        // 过滤掉对应品牌列表里的当前点击项
        this.selectParam.brandList = this.selectParam.brandList.filter(
          i => i !== item.brandId
        )
      } else {
        // 点击选中操作 
       // 设置第三层列表项的数据
        this.newModelData = item.modelList
       // 向对应品牌列表里添加当前点击的品牌id
        this.selectParam.brandList.push(item.brandId)
      }
      // 如果品牌列表为空
      if (this.selectParam.brandList.length === 0) {
        delete this.selectParam.brandList  // 删除筛选参数中的品牌列表属性
        this.isModel = false  // 隐藏第三层列表
      }
      this.$forceUpdate()  // 强制页面更新(重点)
    },
 const mapList = {
     brandId1:[modelId1,model2,...],
     brandId2:[modelId1,model2,...],
     ...
}

上代码:

// 车型选择
    handleSelectModel (item) {
      if (!this.selectParam.modelList) this.selectParam.modelList = []
      if (!this.modelMap[item.brandId]) this.modelMap[item.brandId] = []
      if (this.modelMap[item.brandId].indexOf(item.modelId) > -1) {
        this.modelMap[item.brandId] = this.modelMap[item.brandId].filter(
          i => i !== item.modelId
        )
        if (this.modelMap[item.brandId].length === 0) {
          delete this.modelMap[item.brandId]
        }
      } else {
        this.modelMap[item.brandId].push(item.modelId)
      }
      let modelList = Object.values(this.modelMap)
      if (modelList.length === 0) {
        delete this.selectParam.modelList
      } else {
        this.selectParam.modelList = [].concat(...modelList)
      }
      this.$forceUpdate()
    },

总结

当拿到一个复杂的页面时首先要分析业务需求理清业务逻辑,然后根据接口数据格式去构思页面结构,这样子写起来相对轻松一点。

上一篇 下一篇

猜你喜欢

热点阅读