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


Posted in Javascript onMay 12, 2019
  • 绑定一个 [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组件,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
Sep 13 Javascript
图片在浏览器中底部对齐 解决方法之一
Nov 30 Javascript
javascript时区函数介绍
Sep 14 Javascript
IE6浏览器下resize事件被执行了多次解决方法
Dec 11 Javascript
jquery 字符串切割函数substring的用法说明
Feb 11 Javascript
js获取数组的最后一个元素
Apr 14 Javascript
thinkphp实现无限分类(使用递归)
Dec 19 Javascript
asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)
May 05 Javascript
JS高级运动实例分析
Dec 20 Javascript
JS实现控制图片显示大小的方法【图片等比例缩放功能】
Feb 18 Javascript
Typescript的三种运行方式(小结)
Sep 18 Javascript
在vue中使用Echarts画曲线图的示例
Oct 03 Javascript
vue组件中watch props根据v-if动态判断并挂载DOM的问题
May 12 #Javascript
用js简单提供增删改查接口
May 12 #Javascript
electron-vue利用webpack打包实现多页面的入口文件问题
May 12 #Javascript
vue中axios实现数据交互与跨域问题
May 12 #Javascript
jquery3和layui冲突导致使用layui.layer.full弹出全屏iframe窗口时高度152px问题
May 12 #jQuery
JS块级作用域和私有变量实例分析
May 11 #Javascript
微信小程序封装的HTTP请求示例【附升级版】
May 11 #Javascript
You might like
PHP连接access数据库
2008/03/27 PHP
php smarty模版引擎中的缓存应用
2009/12/11 PHP
php生成二维码的几种方式整理及使用实例
2013/06/03 PHP
ThinkPHP 3.2 数据分页代码分享
2014/10/14 PHP
php实现图片局部打马赛克的方法
2015/02/11 PHP
PHP实现一维数组转二维数组的方法
2015/02/25 PHP
Javascript 陷阱 window全局对象
2008/11/26 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
用正则表达式替换图片地址img标签
2013/11/22 Javascript
javascript运行机制之this详细介绍
2014/02/07 Javascript
jQuery实现冻结表头的方法
2015/03/09 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
2016/01/26 Javascript
Bootstrap Table使用方法详解
2016/08/01 Javascript
js实现3d悬浮效果
2017/02/16 Javascript
vue中组件的3种使用方式详解
2019/03/23 Javascript
echarts 使用formatter 修改鼠标悬浮事件信息操作
2020/07/20 Javascript
python实现图书馆研习室自动预约功能
2018/04/27 Python
python版本的仿windows计划任务工具
2018/04/30 Python
python中使用iterrows()对dataframe进行遍历的实例
2018/06/09 Python
解决python3捕获cx_oracle抛出的异常错误问题
2018/10/18 Python
python的几种矩阵相乘的公式详解
2019/07/10 Python
Django User 模块之 AbstractUser 扩展详解
2020/03/11 Python
python3 简单实现组合设计模式
2020/07/02 Python
python中requests模拟登录的三种方式(携带cookie/session进行请求网站)
2020/11/17 Python
澳大利亚领先的在线药房:Pharmacy Online(有中文站)
2020/02/22 全球购物
C#面试题问题集
2016/04/02 面试题
护士长竞聘书
2014/03/31 职场文书
面试自我评价范文
2014/09/17 职场文书
出纳年终工作总结2014
2014/12/05 职场文书
股权转让协议书
2014/12/07 职场文书
基石观后感
2015/06/12 职场文书
数学备课组工作总结
2015/08/12 职场文书
普希金的诗歌赏析(3首)
2019/08/20 职场文书
普希金诗歌赏析(6首)
2019/08/22 职场文书
python基于tkinter制作无损音乐下载工具
2021/03/29 Python
ubuntu如何搭建vsftpd服务器
2022/12/24 Servers