欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于elementUI使用v-model实现经纬度输入的vue组件

程序员文章站 2023-12-13 15:18:04
绑定一个 [12.34,-45.67] (东经西经,南纬北纬 正负表示) 形式的经纬度数组,能够按度分秒进行编辑,效果如下所示,点击东经,北纬可切换。...
  • 绑定一个 [12.34,-45.67] (东经西经,南纬北纬 正负表示) 形式的经纬度数组,能够按度分秒进行编辑,效果如下所示,点击东经,北纬可切换。
  • 经纬度的 度转度分秒
  • 能够获取度分秒格式数据  

基于elementUI使用v-model实现经纬度输入的vue组件

coordinates组件实现

模板

一个span显示东经西经,三个输入框输入度分秒

<template>
 <div class="coordinates">
  <!-- 经度 -->
  <div class="item">
   <span class="itude"
      @click="itudechange(true)">{{ longflag | longitudename }}</span>
   <el-input v-model.number="longitude[0]"
        @change="change(true,0)"
        size="mini">
    <i slot="suffix">°</i>
   </el-input>
   <el-input v-model.number="longitude[1]"
        @change="change(true,1)"
        size="mini">
    <i slot="suffix">′</i>
   </el-input>
   <el-input v-model.number="longitude[2]"
        @change="change(true,2)"
        size="mini">
    <i slot="suffix">″</i>
   </el-input>
  </div>
  <!-- 纬度 -->
  <div class="item">
   <span class="itude"
      @click="itudechange(false)">{{ latflag | latitudename }}</span>
   <el-input v-model.number="latitude[0]"
        @change="change(false,0)"
        size="mini">
    <i slot="suffix">°</i>
   </el-input>
   <el-input v-model.number="latitude[1]"
        @change="change(false,1)"
        size="mini">
    <i slot="suffix">′</i>
   </el-input>
   <el-input v-model.number="latitude[2]"
        @change="change(false,2)"
        size="mini">
    <i slot="suffix">″</i>
   </el-input>
  </div>
 </div>
</template>

实现

props: 父组件传入的参数 value ,验证合法性 经度绝对值小于180,纬度绝对值小于90,数组长度为2

value: { //绑定的 value
 type: array,
 require: true,
 validator: function (value) {
  let len = value.length > 0 && value.length === 2
  let isvalid = math.abs(value[0]) < 180 && math.abs(value[1]) < 90
  return len && isvalid
 },
 default: function () {
  return []
 }
}

model: prop为 value 时不用实现 model 但是this.$emit(event,arg) 传入的event需要为 'input',这里要注意

model: { 
 prop: 'value',
 event: 'input'
},

v-model实现: 使用this.$emit(event,arg)修改父组件的数据

/**
 * v-model 绑定事件 双向绑定实现
 */
returnbackfn () {
 let longitude = parsefloat(this.longflag + this.dms2d(this.longitude));
 let latitude = parsefloat(this.latflag + this.dms2d(this.latitude));
 let array = [longitude, latitude]
 this.$emit('input', array);
},

coordinates组件完整代码

<template>
 <div class="coordinates">
  <!-- 经度 -->
  <div class="item">
   <span class="itude"
      @click="itudechange(true)">{{ longflag | longitudename }}</span>
   <el-input v-model.number="longitude[0]"
        @change="change(true,0)"
        size="mini">
    <i slot="suffix">°</i>
   </el-input>
   <el-input v-model.number="longitude[1]"
        @change="change(true,1)"
        size="mini">
    <i slot="suffix">′</i>
   </el-input>
   <el-input v-model.number="longitude[2]"
        @change="change(true,2)"
        size="mini">
    <i slot="suffix">″</i>
   </el-input>
  </div>
  <!-- 纬度 -->
  <div class="item">
   <span class="itude"
      @click="itudechange(false)">{{ latflag | latitudename }}</span>
   <el-input v-model.number="latitude[0]"
        @change="change(false,0)"
        size="mini">
    <i slot="suffix">°</i>
   </el-input>
   <el-input v-model.number="latitude[1]"
        @change="change(false,1)"
        size="mini">
    <i slot="suffix">′</i>
   </el-input>
   <el-input v-model.number="latitude[2]"
        @change="change(false,2)"
        size="mini">
    <i slot="suffix">″</i>
   </el-input>
  </div>
 </div>
</template>
<script>
require('math')
export default {
 name: 'coordinates',
 props: {
  value: { //绑定的 value
   type: array,
   require: true,
   validator: function (value) {
    let len = value.length > 0 && value.length === 2
    let isvalid = math.abs(value[0]) < 180 && math.abs(value[1]) < 90
    return len && isvalid
   },
   default: function () {
    return []
   }
  }
 },
 // model: { // prop为 value 时不用实现 model 但是this.$emit(event,arg) 传入的event需要为 'input'
 //  prop: 'value',
 //  event: 'returnback'
 // },
 data () {
  return {
   longitude: [], // 经度
   latitude: [],  // 纬度
   longflag: '+', //表示东经西经
   latflag: '+',  //表示南纬北纬
  }
 },
 created: function () {
  this.initdata();
 },
 filters: {
  longitudename (value) {
   return value === '+' ? "东经" : "西经"
  },
  latitudename (value) {
   return value === '+' ? "南纬" : "北纬"
  }
 },
 watch: {
  /**
  * 监测父组件绑定的value
  */
  value () {
   this.initdata();
  }
 },
 computed: {
  // 转换为  东经 xxx°xx′xx″  格式 
  // 返回一个经纬度的数组
  formatstring () {
   let longitude = (this.longflag === '+' ? "东经 " : "西经 ") + this.longitude[0] + '°' + this.longitude[1] + '′' + this.longitude[2] + '″';
   let latitude = (this.latflag === '+' ? "南纬 " : "北纬 ") + this.latitude[0] + '°' + this.latitude[1] + '′' + this.latitude[2] + '″';
   return [longitude, latitude]
  }
 },
 methods: {
  /**
   * 东经西经,南纬北纬 change事件
   */
  itudechange (flag) {
   flag ? (this.longflag = (this.longflag === '+' ? '-' : '+')) : (this.latflag = (this.latflag === '+' ? '-' : '+'))
   this.returnbackfn()
  },
  /**
   * 初始化数据,父组件修改绑定的value时调用
   */
  initdata () {
   this.longitude = this.d2dms(math.abs(this.value[0]));
   this.latitude = this.d2dms(math.abs(this.value[1]));
   this.longflag = this.value[0] < 0 ? '-' : '+'
   this.latflag = this.value[1] < 0 ? '-' : '+'
  },
  /**
   * 输入框change事件,数据合法性验证
   */
  change (flag, index) {
   let name = '', max = 0
   flag ? [name, max] = ['longitude', 179] : [name, max] = ['latitude', 89]
   index ? max = 59 : null
   let value = parseint(this[name][index], 10)
   if (isnan(value)) {
    value = 0;
   }
   value = value < 0 ? 0 : value
   value = value > max ? max : value
   this.$set(this[name], index, value)
   this.returnbackfn()
  },
  /**
   * v-model 绑定事件 双向绑定实现
   */
  returnbackfn () {
   let longitude = parsefloat(this.longflag + this.dms2d(this.longitude));
   let latitude = parsefloat(this.latflag + this.dms2d(this.latitude));
   let array = [longitude, latitude]
   this.$emit('input', array);
  },
  /**
  * 度转度分秒
  */
  d2dms (d_data = 0) {
   var degree = parseint(d_data);
   var min = parseint((d_data - degree) * 60);
   var sec = parseint((d_data - degree) * 3600 - min * 60);
   return [degree, min, sec];
  },
  /**
  * 度分秒转度
  */
  dms2d (dms_data = [0, 0, 0]) {
   let d = parsefloat(dms_data[0]);
   let m = parsefloat(dms_data[1]);
   let s = parsefloat(dms_data[2]);
   return this.keepfourdecimal(d + m / 60 + s / 60 / 60);
  },
  /**
  * 保留四位小数,小于四位精度可能丢失
  */
  keepfourdecimal (num) {
   var result = parsefloat(num);
   if (isnan(result)) {
    return 0;
   }
   result = math.round(num * 10000) / 10000;
   return result;
  }
 },
}
</script>
<style lang="less" scoped>
@color-border: #9e9e9e;
@height: 28px;
.coordinates {
 border: 1px solid @color-border;
 width: fit-content;
 display: inline-flex;
}
.item:nth-of-type(1) {
 border-right: 1px solid @color-border;
}
.el-input {
 width: 40px;
}
.itude {
 height: @height;
 line-height: @height;
 display: inline-block;
 padding-left: 5px;
 cursor: pointer;
 user-select: none;
}
i {
 font-size: 18px;
 color: gray;
}
</style>
<style lang="less">
.el-input__inner {
 text-align: center;
 border: none;
 border-radius: unset;
}
.el-input--suffix .el-input__inner {
 padding: 0;
}
</style>

测试代码 index.vue

<template>
 <div id="example">
  <coordinates ref="coordinates"
         v-model="value"></coordinates>
  <el-button @click="changevalue"
        type="primary">
   change value
  </el-button>
  <br>
  <span>value:{{value.tostring()}}</span>
  <br>
  <span>度分秒格式:{{formatstring.tostring()}}</span>
  <el-button @click="refresh"
        type="primary">
   refresh
  </el-button>
 </div>
</template>
<script>
import coordinates from '@/components/coordinates'
export default {
 name: 'index',
 components: {
  coordinates
 },
 data () {
  return {
   value: [12.34, -45.67],
   formatstring: []
  }
 },
 mounted () {
  this.refresh ()
 },
 methods: {
  changevalue () {
   this.$set(this.value, 0, (this.value[0] + 2) >= 180 ? 0 : (this.value[0] + 2))
   this.$set(this.value, 1, (this.value[1] + 2) >= 90 ? 0 : (this.value[1] + 2))
   settimeout(() => {
    refresh ()
   }, 10);
  },
  refresh () {
   // 获取度分秒格式
   this.formatstring = this.$refs.coordinates.formatstring
  }
 }
}
</script>
<style lang="less" scoped>
#example {
 padding: 20px;
}
.el-button {
 margin: 20px;
}
span {
 font-size: 17px;
}
</style>

效果

修改子组件值 父组件的value会改变,修改父组件的value,子组件会自动修改, [change value] 按钮 可以修改value [refresh] 按钮 通过ref获取度分秒格式的经纬度

    基于elementUI使用v-model实现经纬度输入的vue组件
    基于elementUI使用v-model实现经纬度输入的vue组件

总结

以上所述是小编给大家介绍的基于elementui使用v-model实现经纬度输入的vue组件,希望对大家有所帮助

上一篇:

下一篇: