zoukankan      html  css  js  c++  java
  • vue手动制作地址选择器

    方法一:4级地址选择器(基于elementui   Cascader 级联选择器) 推荐

    效果图:

     组件源码:

    <template>
      <div class="select-city" ref="selectCity">
        <el-cascader
          :options="options2"
          @change="change"
          v-model="selCity"
          :props="props"
        ></el-cascader>
      </div>
    
    </template>
    
    <style>
      .select-city .el-input{
         350px;
      }
    </style>
    
    <script>
      import addressData from 'common/json/class4new.json'
      export default {
        props: {
          value: {
            required: true
          },
          getCityName: {
    
          }
        },
        data() {
          return {
            options2: addressData,
            props: {
              label: 'name',
              value: 'id',
              children: 'children'
            },
            selCity: []
          }
        },
        watch: {
          value (val) {
            this.init()
          }
        },
        created() {
          // 组件刚载入并不会触发watch value
        },
        methods: {
          init() {
            let el = this.$refs.selectCity
            if (!this.value) {
              if (this.selCity.length) {
                this.selCity = []
                el.getElementsByClassName('el-cascader__label')[0].innerHTML = ''
                el.getElementsByClassName('el-input__inner')[0].setAttribute('placeholder', '请选择')
              }
            } else {
              if (this.selCity.length===0 || this.selCity[3] !== this.value) {
                this.selCity[0] = this.value.substr(0, 2) + '0000'
                this.selCity[1] = this.value.substr(0, 4) + '00000000'
                this.selCity[2] = this.value.substr(0, 6) + '000000'
                this.selCity[3] = this.value
                let name = this.getNode().join('<span>/</span>')
                el.getElementsByClassName('el-cascader__label')[0].innerHTML = name
                el.getElementsByClassName('el-input__inner')[0].setAttribute('placeholder', '')
              }
            }
          },
          change(val) {
            // 只有选完了,才会将数据返回给父组件
            this.$emit('input', val[3])
            this.returnCityName()
          },
          returnCityName() {
            if (typeof this.getCityName === 'function') {
              this.getCityName(this.getNode().join(''))
            }
          },
          getNode() {
            let name = []
            this.options2.filter(v => {
              if (name[0]) return
              if (v.id===this.selCity[0]) {
                name.push(v.name)
                v.children.filter(v => {
                  if (name[1]>0) return
                  if (v.id===this.selCity[1]) {
                    name.push(v.name)
                    v.children.filter(v => {
                      if (name[2]>0) return
                      if (v.id===this.selCity[2]) {
                        name.push(v.name)
                        v.children.filter(v => {
                          if (name[3]>0) return
                          if (v.id===this.selCity[3]) {
                            name.push(v.name)
                            return false
                          }
                        })
                      }
                    })
                  }
                })
              }
            })
            return name
          }
        }
      }
    </script>

    方法二:4级地址选择器(基于elementui  select选择器 )

    适用环境: PC

    开发过程中遇到的问题:

    1. 自定义组件如何做到双向数据绑定

    2. 自定义组件在刚加载完毕,会执行一次created和mounted,当组件上绑定的v-model变化时候,也就是做编辑的时候,触发的watch监听的value方法

    3.这个程序刚好是一个自循环,一旦更新了地址组件绑定的值立刻就触发this.$emit,把执行结果返回至父组件。这边需要visible-change(下拉框出现/隐藏时触发, 出现则为 true,隐藏则为 false),来组件地址组件数据的初始化,导致向父组件传递错误数据

    小小的程序,把我折腾了好几天,仔细想想,两个2原因:1.缺少自己写组件的经历导致对vue的很多api不熟悉  2.缺乏独自面对困难的恒心

    效果图:

    地址组件代码:

    <style>
      .block .el-select{display: block;}
      .block .el-select{margin-bottom: 20px}
    </style>
    
    <template>
      <div>
        <div :class="{block: block}">
          <el-select v-model="proviceCode" popper-class="tab-select" placeholder="请选择省" @change="proviceChange" @visible-change="vChange($event, 'provice')">
            <el-option
              v-for="(item, index) in provice"
              :key="item.id"
              :label="item.name"
              :value="item.id">
            </el-option>
          </el-select>
          <el-select v-model="cityCode" popper-class="tab-select" placeholder="请选择市" @change="cityChange" @visible-change="vChange($event, 'city')">
            <el-option
              v-for="(item, index) in city"
              :key="item.id"
              :label="item.name"
              :value="item.id">
            </el-option>
          </el-select>
          <el-select v-model="areaCode" popper-class="tab-select" placeholder="请选择区或县" @change="areaChange" @visible-change="vChange($event, 'area')">
            <el-option
              v-for="(item, index) in area"
              :key="item.id"
              :label="item.name"
              :value="item.id">
            </el-option>
          </el-select>
          <el-select v-model="villageCode"  popper-class="tab-select" placeholder="请选择乡" @change="villageChange"  @visible-change="vChange($event, 'village')">
            <el-option
              v-for="(item, index) in village"
              :key="item.id"
              :label="item.name"
              :value="item.id">
            </el-option>
          </el-select>
          <input type="hidden" :value="value">
        </div>
      </div>
    </template>
    
    <script>
      import address from 'common/json/class4new.json'
      export default {
        props: {
          block: {
            type: Boolean,
            default: false
          },
          value: {
            required: false
          }
        },
        data() {
          return {
            provice: address,
            city: [],
            area: [],
            village: [],
            proviceCode: '',
            cityCode: '',
            areaCode: '',
            villageCode: '',
            isOpen: {
              provice: false,
              city: false,
              area: false,
              village: false
            }
          }
        },
        watch: {
          value (val) {
            if (val.code !== this.villageCode) {
              this.init()
            }
          }
        },
        created() {
          this.villageCode = this.value.code
          this.init()
        },
        mounted () {
          this.$root.eventHub.$on("reset-addressSelect", () => {
            this.city = []
            this.area = []
            this.village = []
            this.proviceCode = ''
            this.cityCode = ''
            this.areaCode = ''
            this.villageCode = ''
          })
        },
        methods: {
          vChange(val, type) {
            this.isOpen[type] = val
          },
          init() {
            let code = this.value.code;
            if (code) {
              let v = code.toString()
              this.proviceCode = v.substr(0,2) + '0000'
              this.cityCode = v.substr(0,4)+'00000000'
              this.areaCode = v.substr(0,6)+'000000'
              this.villageCode = v
              this.proviceChange(this.proviceCode).then(_ => {
                this.cityChange(this.cityCode).then(_ => {
                  this.areaChange(this.areaCode)
                })
              })
            } else {
              this.city = []
              this.area = []
              this.village = []
              this.proviceCode = ''
              this.cityCode = ''
              this.areaCode = ''
              this.villageCode = ''
            }
          },
          proviceChange(id) {
            return new Promise((resolve, reject) => {
              if (this.isOpen.provice) {
                this.city = []
                this.area = []
                this.village = []
                this.cityCode = ''
                this.areaCode = ''
                this.villageCode = ''
              }
              this.provice.filter(v => {
                if (v.id === id) {
                  this.city = v.children
                  resolve()
                  return false
                }
              })
            })
          },
          cityChange(id) {
            return new Promise((resolve, reject) => {
              if (this.isOpen.city) {
                this.area = []
                this.village = []
                this.areaCode = ''
                this.villageCode = ''
              }
              this.city.filter(v => {
                if (v.id === id) {
                  this.area = v.children
                  resolve()
                  return false
                }
              })
            })
          },
          areaChange(id) {
            return new Promise((resolve, reject) => {
              if (this.isOpen.area) {
                this.village = []
                this.villageCode = ''
              }
              this.area.filter(v => {
                if (v.id === id) {
                  this.village = v.children
                  resolve()
                  return false
                }
              })
            })
          },
          villageChange(id) {
            var text = []
            this.provice.filter(v => {
              if (v.id === this.proviceCode) {
                text.push(v.name)
                return false
              }
            })
            this.city.filter(v => {
              if (v.id === this.cityCode) {
                text.push(v.name)
                return false
              }
            })
            this.area.filter(v => {
              if (v.id === this.areaCode) {
                text.push(v.name)
                return false
              }
            })
            this.village.filter(v => {
              if (v.id === id) {
                text.push(v.name)
                return false
              }
            })
            this.$emit('input', {
              text: text.join(''),
              code: id
            })
          }
        }
      }
    </script>
  • 相关阅读:
    智器SmartQ T7实体店试用体验
    BI笔记之SSAS库Process的几种方案
    PowerTip of the Day from powershell.com上周汇总(八)
    PowerTip of the Day2010071420100716 summary
    PowerTip of the Day from powershell.com上周汇总(十)
    PowerTip of the Day from powershell.com上周汇总(六)
    重新整理Cellset转Datatable
    自动加密web.config配置节批处理
    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable
    在VS2003中以ClassLibrary工程的方式管理Web工程.
  • 原文地址:https://www.cnblogs.com/zph666/p/7661524.html
Copyright © 2011-2022 走看看