computed怎么使用_使用 element-ui 级联插件遇到的坑

需求描述【省市区三级联动】

组件:Cascader 级联选择器

  • 后端需要所选中的地区的名字,如:['北京市', '北京市', '东城区']
  • 获取后端省市区具体列表的接口返回数据:
// 省 - 参数1
[
  {
    value: 1,
    label: '北京市'
  },
  ...
]
// 市 - 参数2
[
  {
    value: 1,
    label: '北京市'
  },
  ...
]
// 区 - 参数3
[
  {
    value: 1,
    label: '东城区'
  },
  ...
]
  • 因 element-ui 级联选择器 Cascader 有可以直接获取指定字段的属性,所以直接使用
{
    value: this.label
}
  • 一般情况下都没有问题,偶然发现当省市区有名字一样时出现没有值选中的情况,如:['北京市', '北京市', '东城区']

2ff5e4b3317f031542b3416b41384b56.png
  • 发现接口也有点问题

9d0fab90d77b3bcfd3c3c728e803f038.png


组件的回调级别 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;
 }

e8c12423ec7e2f04e29aeb45b460d33e.png

  • 既然组件是必须唯一找到才能正常,那我只能设置一个唯一的值了,把层级【级别】也加到里面去,这样就能显示唯一的,最后返回出来时再把层级【级别】去掉就好了
    > 本来是想用 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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值