vue el-cascader 省市区封装及使用

使用了 Element UI 中的 el-cascader 组件,并对其进行了进一步封装和定制

创建组件index.vue (src/components/addressCascader/index.vue)
<template>
  <div>
    <el-cascader
        v-if="showca"
        size="large"
        :props="props"
        :options="cascaderOption"
        :placeholder="placeholder || '选择省/市/区'"
        v-model="selectedOptions"
        @change="addressChange"
        ref="place"
        :disabled="disabled"
        :clearable="clearable"
        :popper-class=" 'cascader-default'
      "
    >
    </el-cascader>
  </div>
</template>

<script>
  import { getDistrictAllSelect, getDistrictFilterSelect } from '@/api/district'
  export default {
    props: {
      selectedVal: {
        type: [Number, String],
        default: ''
      },
      disabled: {
        type: Boolean,
        default: false
      },
      checkStrictly: {
        type: Boolean,
        default: false
      },
      isNeedFilter: {
        type: Boolean,
        default: true
      },
      clearable: {
        type: Boolean,
        default: false
      },
      placeholder: String
    },
    data () {
      return {
        props: {
          value: 'id',
          label: 'name',
          checkStrictly: this.checkStrictly,
          expandTrigger: 'hover'
        },
        newDistictId: '',
        selectedOptions: [],
        showca: true,
        timeout: null,
        isChoose: false,
        chooseLevel: 0,
        cascaderOption: [],
        originData: [],
        cascaderList: []
      }
    },
    watch: {
      selectedVal: {
        handler (val) {
          if (val) {
            if(this.originData.length>0) {
              this.cascaderList = []
              this.findParent(Number(this.selectedVal))
              this.cascaderList.push(Number(this.selectedVal))
              this.selectedOptions = this.cascaderList
              this.$nextTick(() => {
                let label = this.$refs.place.getCheckedNodes()
                    ? this.$refs.place.getCheckedNodes()[0].pathLabels
                        ? this.$refs.place.getCheckedNodes()[0].pathLabels.join('')
                        : ''
                    : ''
                let level = this.$refs.place.getCheckedNodes()
                    ? this.$refs.place.getCheckedNodes()[0].level
                    : ''

                this.$emit(
                    'getVal',
                    this.selectedOptions[this.selectedOptions.length - 1],
                    label,
                    level
                )
              })
            }
          } else {
            this.clearVal()
          }
        },
        immediate: true
      }
    },
    mounted () {
      this.getDistrictAllSelect()
    },
    beforeDestroy () {},
    methods: {
      findParent (idx) {
        this.originData.forEach(item => {
          if (idx.toString() === item.id.toString()) {
            let pid = item['parentId']

            if (pid !== 0) {
              this.cascaderList.unshift(pid)
              this.findParent(pid)
            }
          }
        })
      },

      addressChange (arr) {
        if (arr.length > 1) {
          this.isChoose = true
        }
        if (arr.length == 1) {
          this.chooseLevel = 0
        } else if (arr.length == 2) {
          this.chooseLevel = 1
        } else if (arr.length == 3) {
          this.chooseLevel = 3
        }
        if (arr.length == 0) {
          this.$emit('getVal', '')
          return
        }
        console.log(
            this.$refs.place.getCheckedNodes()[0],
            'this.$refs.place.getCheckedNodes()[0]'
        )
        let label = this.$refs.place.getCheckedNodes()[0].pathLabels
            ? this.$refs.place.getCheckedNodes()[0].pathLabels.join('')
            : ''
        let level = this.$refs.place.getCheckedNodes()[0].level

        this.$emit('getVal', arr[arr.length - 1], label, level)
        if (arr.length > 2) {
          this.$refs.place.dropDownVisible = false
        }
      },
      clearVal () {
        if (this.$refs.place) {
          this.selectedOptions = []
          this.$refs.place.$refs.panel.checkedValue = []
          this.$refs.place.$refs.panel.activePath = []
          this.$refs.place.$refs.panel.syncActivePath()
        }
      },
      async getDistrictAllSelect () {

        let data
        if (this.checkStrictly && this.isNeedFilter) {
          data = await getDistrictFilterSelect()
          this.originData = data || []
          this.cascaderOption = this.transTree(data)
        } else {
          if (sessionStorage.pvRegionData&&sessionStorage.pvRegionOriginData!='undefined') {
            this.originData = JSON.parse(sessionStorage.pvRegionOriginData)
            this.cascaderOption = JSON.parse(sessionStorage.pvRegionData)
          } else {
            data = await getDistrictAllSelect()
            this.originData = data || []
            sessionStorage.setItem('pvRegionOriginData', JSON.stringify(data))
            this.cascaderOption = this.transTree(data)
            sessionStorage.setItem(
                'pvRegionData',
                JSON.stringify(this.cascaderOption)
            )
          }
        }
        if (this.selectedVal) {
          this.cascaderList = []
          this.findParent(Number(this.selectedVal))
          this.cascaderList.push(Number(this.selectedVal))
          this.selectedOptions = this.cascaderList
          this.$nextTick(() => {
            let label = this.$refs.place.getCheckedNodes()
                ? this.$refs.place.getCheckedNodes()[0].pathLabels
                    ? this.$refs.place.getCheckedNodes()[0].pathLabels.join('')
                    : ''
                : ''
            let level = this.$refs.place.getCheckedNodes()
                ? this.$refs.place.getCheckedNodes()[0].level
                : ''

            this.$emit(
                'getVal',
                this.selectedOptions[this.selectedOptions.length - 1],
                label,
                level
            )
          })
        }
      },
      transTree (data) {
        let result = []
        let map = {}
        if (!Array.isArray(data)) {
          //验证data是不是数组类型
          return []
        }
        data.forEach(item => {
          //建立每个数组元素id和该对象的关系
          map[item.id] = item //这里可以理解为浅拷贝,共享引用
        })
        data.forEach(item => {
          let parent = map[item.parentId] //找到data中每一项item的爸爸
          if (parent) {
            //说明元素有爸爸,把元素放在爸爸的children下面
            ;(parent.children || (parent.children = [])).push(item)
          } else {
            //说明元素没有爸爸,是根节点,把节点push到最终结果中
            result.push(item) //item是对象的引用
          }
        })
        return result //数组里的对象和data是共享的
      }
    }
  }
</script>

<style scoped lang="scss"></style>





页面引入
  • 在需要使用addressCascader组件的地方,通过import语句引入组件注册并使用

<template>
  <div>
    <address-cascader
        :selectedVal="selectedValue"
        @getVal="
              (districtVal, districtLabel, districtLevel) =>
                setDistrictId(districtVal, districtLabel, info, districtLevel)
            "
        :isNeedFilter="info.isNeedFilter"
        :checkStrictly="info.checkStrictly"
        ref="addressCascader"
        :disabled="info.disabled"
    ></address-cascader>
  </div>
</template>
<script>
  import addressCascader from "@/components/addressCascader/index";

  export default {
    components: {
      addressCascader
    },
    data() {
      return {
        info:{
          clearable: true,
          isNeedFilter:false,
          valueFormat:'yyyy-MM-dd',
          checkStrictly: false,
          pickerOptions:{}
        },
        dataSource: [],
        selectedValue: ''
      }
    },
    methods: {
      setDistrictId(val, label, info, districtLevel) {
        console.log("选中的值,文字,信息,级别", val, label, info, districtLevel);
      }
    }
    // ...
  }
</script>

确保你已经安装了Vue.js和Element UI,并在项目中引入它们。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值