首页 > 编程 > JavaScript > 正文

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

2019-11-19 11:36:03
字体:
来源:转载
供稿:网友
  • 绑定一个 [12.34,-45.67] (东经西经,南纬北纬 正负表示) 形式的经纬度数组,能够按度分秒进行编辑,效果如下所示,点击东经,北纬可切换。
  • 经纬度的 度转度分秒
  • 能够获取度分秒格式数据  

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组件,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表