使用 element-ui 級聯插件遇到的坑

需求描述【省市區三級聯動】

組件:Cascader 級聯選擇器

  • 後端需要所選中的地區的名字,如:['北京市', '北京市', '東城區']
  • 獲取後端省市區具體列表的接口返回數據:
// 省 - 參數1
[
  {
    value: 1,
    label: '北京市'
  },
  ...
]
// 市 - 參數2
[
  {
    value: 1,
    label: '北京市'
  },
  ...
]
// 區 - 參數3
[
  {
    value: 1,
    label: '東城區'
  },
  ...
]
  • 因 element-ui 級聯選擇器 Cascader 有可以直接獲取指定字段的屬性,所以直接使用
{
    value: this.label
}
  • 一般情況下都沒有問題,偶然發現當省市區有名字一樣時出現沒有值選中的情況,如:['北京市', '北京市', '東城區']
  • 發現接口也有點問題

    組件的回調級別 level 在相同內容的情況下,返回的一直是最上層的節點,猜想可能是 level 的判斷的問題,於是只能找源碼了

經常不斷打斷點終於找到的原因所在

  • 問題原因:查找節點的方法,不管當前找到了幾個節點,都會只返回第一個節點,然後第一個節點肯定是在最前面的所以級別最高 level 是1,這個應該是一個問題,還得想下怎麼才能解決自己的問題
 // cascader-panel/src/store.js
 
 getNodeByValue(value) {
    if (value) {
        const nodes = this.getFlattedNodes(false, !this.config.lazy)
            .filter(node => (valueEquals(node.path, value) || node.value === value));
        return nodes && nodes.length ? nodes[0] : null;
    }
    return null;
 }


  • 既然組件是必須唯一找到才能正常,那我只能設置一個唯一的值了,把層級【級別】也加到裏面去,這樣就能顯示唯一的,最後返回出來時再把層級【級別】去掉就好了

本來是想用 computed 做轉換的,結果發現轉換有問題,只能用 watch 了,感覺 watch 性能可能會不大好,自己一般情況下能用 computed 解決的絕不用 watch 的

  • 組件實現代碼:

顯示的值還是 label
比對的值是 value, 確定唯一的值
返回到父組件的值要做對應的去格式化處理

<template>
  <div class="the-city-cascader">
    <el-cascader
      class="city-cascader"
      :separator="separator"
      v-on="$listeners"
      v-bind="$attrs"
      v-model="innerValue"
      :options="cityOptions"
      :props="cascaderProps"
      @change="changeHandle"
    >
    </el-cascader>
  </div>
</template>

<script>
export default {
  name: 'the-city-cascader',
  props: {
    value: {
      type: [Array, String],
      default: () => []
    },
    expandTrigger: {
      type: String,
      default: 'click'
    },
    /**
     * value 傳出的字段組
     */
    valueKey: {
      type: String,
      default: 'value',
    },
    separator: {
      type: String,
      default: ' / ',
    },
  },
  data() {
    return {
      cityOptions: [],
      innerValue: [],
      isLazy: true,
    };
  },
  computed: {
    cascaderProps() {
      return {
        expandTrigger: this.expandTrigger,
        value: this.valueKey,
        lazy: true,
        lazyLoad: async (node, resolve) => {
          const { data, level } = node
          let nodes = []
          const findLevel = level + 1
          if (level === 0) {
            nodes = await this.initCityList(findLevel)
          } else {
            nodes = await this.initCityList(findLevel, data.code)
          }
          nodes.forEach(item => {
            if (findLevel < 3) {
              item.leaf = false
            } else {
              item.leaf = true
            }
          })
          // 通過調用resolve將子節點數據返回,通知組件數據加載完成
          resolve(nodes)
        }
      }
    },
  },
  created() {
    this.innerValue = this.value.map((item, itemI) => `${itemI + 1}-${item}`)
  },
  methods: {
    /**
     * 省1市2區3
     */
    async initCityList(flag, areaId = 0) {
      const params = { flag, areaId }
      let result = []
      try {
        const { data, status } = await this.axios.get(this.$API.cascaderCity, { params })
        if (status === 200) {
          result = (data.result || []).map(item => ({
            // 顯示的值
            label: item.label,
            // 值的id
            value: `${flag}-${item.label}`,
            // 接口參數的值
            code: item.value,
          }))
        }
      } catch (error) {
        console.error(error)
      }
      return result
    },
    changeHandle(val) {
      const list = val.map(item => {
        const splitList = item.split('-')
        if (splitList.length > 0) {
          return splitList[1]
        } else {
          return splitList[0]
        }
      })
      this.$emit('input', list)
    }
  }
}
</script>

<style lang="scss" scoped>
.the-city-cascader {
  width: 100%;
  .city-cascader {
    width: 100%;
  }
}
</style>

原文出處:https://www.cnblogs.com/chentingjun/p/11858855.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章