基于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 相关文章推荐
统一接口:为FireFox添加IE的方法和属性的js代码
Mar 25 Javascript
跨域请求之jQuery的ajax jsonp的使用解惑
Oct 09 Javascript
checkbox设置复选框的只读效果不让用户勾选
Aug 12 Javascript
jQuery ajax dataType值为text json探索分享
Sep 23 Javascript
js控制页面控件隐藏显示的两种方法介绍
Oct 09 Javascript
Javascript学习笔记之 对象篇(四) : for in 循环
Jun 24 Javascript
详谈JavaScript 匿名函数及闭包
Nov 14 Javascript
javascript实现图片自动和可控的轮播切换特效
Apr 13 Javascript
jQuery实现表单步骤流程导航代码分享
Aug 28 Javascript
Javascript实现前端简单的路由实例
Sep 11 Javascript
JavaScript事件方法(实例讲解)
Jun 27 Javascript
electron demo项目npm install安装失败的解决方法
Feb 06 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
检测png图片是否完整的php代码
2010/09/06 PHP
smarty模板引擎之内建函数用法
2015/03/30 PHP
PHP实现RTX发送消息提醒的实例代码
2017/01/03 PHP
PHP连接MySQL进行增、删、改、查操作
2017/02/19 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
Javascript 写的简单进度条控件
2008/01/22 Javascript
javascript与CSS复习(二)
2010/06/29 Javascript
页面调用单个swf文件,嵌套出多个方法。
2011/11/21 Javascript
jQuery隐藏和显示效果实现
2016/04/06 Javascript
jQuery实现删除li节点的方法
2016/12/06 Javascript
js实现日历的简单算法
2017/01/24 Javascript
基于Vuejs和Element的注册插件的编写方法
2017/07/03 Javascript
JS实现的简单表单验证功能示例
2017/10/13 Javascript
JavaScript引用类型Date常见用法实例分析
2018/08/08 Javascript
基于vue的验证码组件的示例代码
2019/01/22 Javascript
JavaScript类的继承多种实现方法
2020/05/30 Javascript
win7 下搭建sublime的python开发环境的配置方法
2014/06/18 Python
django实现登录时候输入密码错误5次锁定用户十分钟
2017/11/05 Python
python+pandas分析nginx日志的实例
2018/04/28 Python
Python文件操作方法详解
2020/02/09 Python
Python3实现个位数字和十位数字对调, 其乘积不变
2020/05/03 Python
一张图片能隐含千言万语之隐藏你的程序代码
2012/12/13 HTML / CSS
苹果美国官方商城:Apple美国
2016/08/24 全球购物
美国高品质个性化珠宝销售网站:Jewlr
2018/05/03 全球购物
波兰补充商店:Muscle Power
2018/10/29 全球购物
岗位职责的含义
2013/11/17 职场文书
师范应届毕业生自荐信
2013/11/18 职场文书
2014年社区庆元旦活动方案
2014/03/08 职场文书
学习雷锋活动总结
2014/04/29 职场文书
奥巴马开学演讲稿
2014/05/15 职场文书
我爱我校演讲稿
2014/05/21 职场文书
幼儿园安全责任书范本
2014/07/24 职场文书
2015年科室工作总结
2015/04/10 职场文书
2015年度个人教学工作总结
2015/05/20 职场文书
Go语言中的UTF-8实现
2021/04/26 Golang
PyQt5实现多张图片显示并滚动
2021/06/11 Python