基于elementUI使用v-model實現(xiàn)經(jīng)緯度輸入的vue組件
- 綁定一個 [12.34,-45.67] (東經(jīng)西經(jīng),南緯北緯 正負表示) 形式的經(jīng)緯度數(shù)組,能夠按度分秒進行編輯,效果如下所示,點擊東經(jīng),北緯可切換。
- 經(jīng)緯度的 度轉(zhuǎn)度分秒
- 能夠獲取度分秒格式數(shù)據(jù)

Coordinates組件實現(xiàn)
模板
一個span顯示東經(jīng)西經(jīng),三個輸入框輸入度分秒
<template>
<div class="coordinates">
<!-- 經(jīng)度 -->
<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>
實現(xiàn)
props: 父組件傳入的參數(shù) value ,驗證合法性 經(jīng)度絕對值小于180,緯度絕對值小于90,數(shù)組長度為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 時不用實現(xiàn) model 但是this.$emit(event,arg) 傳入的event需要為 'input',這里要注意
model: {
prop: 'value',
event: 'input'
},
v-model實現(xiàn): 使用this.$emit(event,arg)修改父組件的數(shù)據(jù)
/**
* v-model 綁定事件 雙向綁定實現(xiàn)
*/
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">
<!-- 經(jīng)度 -->
<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 時不用實現(xiàn) model 但是this.$emit(event,arg) 傳入的event需要為 'input'
// prop: 'value',
// event: 'returnBack'
// },
data () {
return {
longitude: [], // 經(jīng)度
latitude: [], // 緯度
longFlag: '+', //表示東經(jīng)西經(jīng)
latFlag: '+', //表示南緯北緯
}
},
created: function () {
this.initData();
},
filters: {
longitudeName (value) {
return value === '+' ? "東經(jīng)" : "西經(jīng)"
},
latitudeName (value) {
return value === '+' ? "南緯" : "北緯"
}
},
watch: {
/**
* 監(jiān)測父組件綁定的value
*/
value () {
this.initData();
}
},
computed: {
// 轉(zhuǎn)換為 東經(jīng) XXX°XX′XX″ 格式
// 返回一個經(jīng)緯度的數(shù)組
formatString () {
let longitude = (this.longFlag === '+' ? "東經(jīng) " : "西經(jīng) ") + 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: {
/**
* 東經(jīng)西經(jīng),南緯北緯 change事件
*/
itudeChange (flag) {
flag ? (this.longFlag = (this.longFlag === '+' ? '-' : '+')) : (this.latFlag = (this.latFlag === '+' ? '-' : '+'))
this.returnBackFn()
},
/**
* 初始化數(shù)據(jù),父組件修改綁定的value時調(diào)用
*/
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事件,數(shù)據(jù)合法性驗證
*/
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 綁定事件 雙向綁定實現(xiàn)
*/
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);
},
/**
* 度轉(zhuǎn)度分秒
*/
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];
},
/**
* 度分秒轉(zhuǎn)度
*/
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);
},
/**
* 保留四位小數(shù),小于四位精度可能丟失
*/
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獲取度分秒格式的經(jīng)緯度


總結(jié)
以上所述是小編給大家介紹的基于elementUI使用v-model實現(xiàn)經(jīng)緯度輸入的vue組件,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!
相關(guān)文章
vue.js表單驗證插件(vee-validate)的使用教程詳解
這篇文章主要介紹了vue.js表單驗證插件(vee-validate)的使用,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05
使用vue-router與v-if實現(xiàn)tab切換遇到的問題及解決方法
這篇文章主要介紹了vue-router與v-if實現(xiàn)tab切換的思考,需要的朋友可以參考下2018-09-09
element?UI中el-dialog實現(xiàn)拖拽功能示例代碼
我們在開發(fā)中常會遇見拖拽的功能,下面這篇文章主要給大家介紹了關(guān)于element?UI中el-dialog實現(xiàn)拖拽功能的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-12-12
vue 驗證碼界面實現(xiàn)點擊后標灰并設(shè)置div按鈕不可點擊狀態(tài)
今天小編就為大家分享一篇vue 驗證碼界面實現(xiàn)點擊后標灰并設(shè)置div按鈕不可點擊狀態(tài),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10

