element-ui 中 el-cascader 按照点击时间排序 tag

315 阅读1分钟

element-plus 中已支持

<!--  -->
<template>
  <el-cascader ref="cascader" v-model="localValue" v-bind="$attrs" @change="change">
    <template #[slotName] v-for="(slot, slotName) in $slots">
      <slot :name="slotName"></slot>
    </template>
  </el-cascader>
</template>

<script>
// 添加根据点击时间顺序显示级联 tag
export default {
  name: 'CascaderInClickOrder',
  props: {
    value: {
      type: Array | String,
      default: ''
    }
  },
  data() {
    return {
      preValue: [],//上次所选值
      echoTag: true,//是否尚未回显过远程数据
    };
  },
  computed: {
    localValue: {
      get() {
        return this.value
      },
      set(value) {
        this.$emit('input', value);
      }
    },
    multiple() {
      return this.$attrs.props.multiple;
    },
    valueFieldName(){
      // value 是 选项数据 option 所绑定的数据中 value 的 字段名默认就是 vlaue
      return this.$attrs.props.value || 'value'
    }
  },
  watch: {
    localValue: {
      handler(nv) {
        if (!this.multiple) return; //不是多选不需要排序
        if (this.echoTag && nv && nv.length > 0) {
          // 回显远程数据时, 进行排序显示, 添加时间戳
          let timestamp = Date.now();
          this.preValue = nv.map(item => {
            item.timestamp = timestamp++;
            return item;
          })
          this.renderSortTag(nv);
          this.echoTag = false;
        }
      },
      immediate: true
    }
  },
  methods: {
    change(v) {
      try {
        if (!this.multiple) throw Error('不是多选不需要排序');

        const findEl = (arr, el) => arr.find(item => item[item.length - 1] === el[el.length - 1])

        // 回显远程数据后 第一次点击新增选项时 远程数据中没有 timestamp 这里将 preValue 中对于的 timestamp 赋予 v
        if (this.preValue && this.preValue.length > 0) v.forEach(el => {
          if (!el.timestamp) {
            const findedEl = findEl(this.preValue, el)
            if (findedEl) el.timestamp = findedEl.timestamp || null;
          }
        });
        // 得到与上次数据 preValue 中的不同项
        const diff = v.filter(el => {
          return findEl(this.preValue, el) ? false : true;
        });
        // 赋予 时间戳
        diff.forEach(el => {
          findEl(v, el).timestamp = Date.now();
        })

        // 根据 timestamp 排序
        this.preValue = v = _.orderBy(v, 'timestamp', 'asc');

        this.renderSortTag(v)
      } catch (error) {
        console.error(error);
      }

      this.$emit('input', v);
      this.$emit('change', v);
    },
    renderSortTag(v) {
      this.$nextTick(() => {
        this.$nextTick(() => {
          this.$refs.cascader.presentTags = v.map(item => {
            return this.$refs.cascader.presentTags.find(node => node.node.data[this.valueFieldName] === item[item.length - 1])
          })
        })
      })
    }
  }
}
</script>
<style scoped></style>