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

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

创建组件index.vue (src/components/addressCascader/index.vue)
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语句引入组件注册并使用
vue 复制代码
<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,并在项目中引入它们。

相关推荐
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
吹牛不交税8 小时前
admin.net-v2 框架使用笔记-netcore8.0/10.0版
vue.js·.netcore
MZ_ZXD00110 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
铅笔侠_小龙虾10 小时前
Flutter 实战: 计算器
开发语言·javascript·flutter
大模型玩家七七10 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
2501_9447114310 小时前
JS 对象遍历全解析
开发语言·前端·javascript
发现一只大呆瓜11 小时前
虚拟列表:支持“向上加载”的历史消息(Vue 3 & React 双版本)
前端·javascript·面试
阔皮大师11 小时前
INote轻量文本编辑器
java·javascript·python·c#
lbb 小魔仙11 小时前
【HarmonyOS实战】React Native 表单实战:自定义 useReactHookForm 高性能验证
javascript·react native·react.js