最近一直在做移動端微信公眾號專案的開發,也是我首次用vue來開發移動端專案,前期積累的移動端開發經驗較少。經過這個專案的鍛鍊,加深了對vue相關知識點的理解和運用,同時,在專案中所涉及到的微信api(微信分享,微信支付),百度地圖api(如何例項化地圖,給地圖新增自定義覆蓋物,給地圖新增自定義標註,對地圖進行縮放,拖拽等)的相關使用,開闊了自己的知識眼界;現將我開發過程中積累的相關經驗與大家進行分享,希望和大家一起學習和進步....
-
vux:Vue 移動端 UI 元件庫的使用;
-
vue-lazyload :一個簡單易用的 Vue 圖片延遲載入外掛;
-
vuex:vue狀態管理工具詳細入門;
-
async/await:非同步神器來封裝介面請求檔案fetch.js
-
vue 專案中的迭代判斷技巧;
-
vue 專案中常用的圖片引入方式;
-
微信api在vue專案中的使用:
-
vue2實現微信分享坑點和經驗 ;
-
vue2實現微信支付坑點和經驗;
-
-
百度地圖api在vue專案中的使用:
-
vue2.0專案中如何使用百度地圖api
-
vue2如何給地圖新增房源覆蓋物;
-
如何給地圖新增自定義定位控制元件並更換控制元件的圖示;
-
如何給地圖新增自定義當前位置定位標註
-
幾個常用的api(地圖縮放,拖拽,獲取當前位置)等功能的實現;
-
VUX - Vue 移動端 UI 元件庫的使用;
vux介紹:詳細請參見官方文件。
由於是做微信公眾號移動端專案,我們對比了幾個vuejs的移動端UI庫,知道vux是基於WeUI和Vue(2.x)開發的移動端UI元件庫,主要服務於微信頁面;雖然它屬於個人維護,體驗上需要一些改進。但專案中幾個元件的使用,大大提升了開發效率。
使用方法如下:
- 安裝- vux:
npm install vux --save
複製程式碼
注意事項:
vux2必須配合vux-loader使用, 請在build/webpack.base.conf.js裡參照如下程式碼進行配置:vux2必須配合vux-loader使用, 請在build/webpack.base.conf.js裡參照如下程式碼進行配置:
const vuxLoader = require('vux-loader')
const webpackConfig = originalConfig // 原來的 module.exports 程式碼賦值給變數 webpackConfig
module.exports = vuxLoader.merge(webpackConfig, {
plugins: ['vux-ui']
})
複製程式碼
- 以輪播元件swiper為例
如果你要使用的元件只是在當前頁面中使用,我們可以只在當前頁面中引入即可。如果在很多頁面中都有使用,可以在main.js中以全域性方式引用。使用元件方法如下:
<template>
<swiper auto loop :interval="interval" :duration="duration" id="swiper-banner"
class="swiper-banner"
:height="height">
<swiper-item
class="swiper-demo-img"
v-for="(item, index) in bannerList"
:key="index">
<img :src="item.img">
</swiper-item>
</swiper>
</template>
<script>
import { Swiper, SwiperItem } from "vux";
export default {
name: "swiper",
data() {
interval:4000,// 輪播停留時間
duration:300// 切換動畫時間
height:"10.19rem", // 高度值
bannerList:[
{img: 'https://static.vux.li/demo/1.jpg',title: '送你一朵fua'},
{img: 'https://static.vux.li/demo/5.jpg',title: '小花'}
]
}
}
</script>
複製程式碼
屬性auto,預設為false,表示是否自動輪播;屬性loop,預設為false,表示是否迴圈;
vue-lazyload :一個簡單易用的 Vue 圖片延遲載入外掛
官方網址:vue-lazyload
介紹: vue-lazyload主要應用於圖片延遲載入。包含如下的特點:
- 小巧輕便,功能強大,易於使用
- 可以用於載入任何影像型別
- 支援Vue 1.0和Vue 2.0
理解圖片延遲載入:
當某個網頁中呈現的圖片較多時,由於網路等原因,訪問該網頁時,所有的圖片不會立馬全部進行顯示出來,會出現一定的網路延遲載入的現象,影響使用者體驗;但我們可以vue-lazyload外掛來實現在圖片載入的過程中,先顯示出預設的載入圖片,直到圖片完全顯示,預設圖片消失,這樣就會大大的提升使用者體驗。
使用方法如下:
1、通過npm安裝
npm install vue-lazyload -s
複製程式碼
2、在main.js中進行引用
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.3, // 預壓高度的比例
error: '../assets/img/no-pic.png', // 影像的載入失敗時 顯示的error圖示
loading: '../assets/imgLoading.png', // 影像正常載入時 顯示的loading圖示
attempt: 1 // 影像嘗試載入 次數
})
複製程式碼
3、在元件中使用
<img v-lazy="item.picUrl" alt="">
複製程式碼
4、實現效果以後,還可以根據API進行功能擴充套件。
相應的引數可參考官方API進行設定。
5、vue-lazyLoad檔案整理,請參照:vue2-plugs-demo專案中src/components/LazyLoad/index.vue 和 src/main.js部分;;
vuex:vue狀態管理工具詳細入門;
vuex介紹:
詳細介紹請參見官方網站。Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 什麼情況下我應該使用 Vuex? 如果您需要構建一箇中大型單頁應用,您很可能會考慮如何更好地在元件外部管理狀態,Vuex 將會成為自然而然的選擇。 使用方法:
- 安裝vuex:
npm install vuex --save
複製程式碼
- 在mins.js中引用:
import Vuex from "vuex";
Vue.use(Vuex);
複製程式碼
理解vuex的5個基本物件:
-
state:儲存狀態。也就是變數;
-
getters:派生狀態。也就是set、get中的get,有兩個可選引數:state、getters分別可以獲取state中的變數和其他的getters。外部呼叫方式:store.getters.personInfo()。就和vue的computed差不多;
-
mutations:提交狀態修改。也就是set、get中的set,這是vuex中唯一修改state的方式,但不支援非同步操作。第一個引數預設是state。外部呼叫方式:store.commit('SET_AGE', 18)。和vue中的methods類似。
-
actions:和mutations類似。不過actions支援非同步操作。第一個引數預設是和store具有相同引數屬性的物件。外部呼叫方式:store.dispatch('nameAsyn')。
-
modules:store的子模組,內容就相當於是store的一個例項。呼叫方式和前面介紹的相似,只是要加上當前子模組名,如:store.a.getters.xxx()。
vue-cli中使用vuex的方式
一般來講,我們都會採用vue-cli來進行實際的開發,在vue-cli中,開發和呼叫方式稍微不同。
├── index.html
├── main.js
├── components
└── store
├── index.js # 我們組裝模組並匯出 store 的地方
├── state.js # 跟級別的 state
├── getters.js # 跟級別的 getter
├── mutation-types.js # 根級別的mutations名稱(官方推薦mutions方法名使用大寫)
├── mutations.js # 根級別的 mutation
├── actions.js # 根級別的 action
└── modules
├── index.js # 模組集合
├── m1.js # 模組1
├── m2.js # 模組2
複製程式碼
state.js示例:
const state = {
name: 'weish',
age: 22
};
export default state;
複製程式碼
getters.js示例(我們一般使用getters來獲取state的狀態,而不是直接使用state):
export const name = (state) => {
return state.name;
}
export const age = (state) => {
return state.age
}
export const other = (state) => {
return `My name is ${state.name}, I am ${state.age}.`;
}
複製程式碼
mutation-type.js示例(我們會將所有mutations的函式名放在這個檔案裡):
export const SET_NAME = 'SET_NAME';
export const SET_AGE = 'SET_AGE';
複製程式碼
mutations.js示例:
import * as types from './mutation-type.js';
export default {
[types.SET_NAME](state, name) {
state.name = name;
},
[types.SET_AGE](state, age) {
state.age = age;
}
};
複製程式碼
actions.js示例(非同步操作、多個commit時):
import * as types from './mutation-type.js';
export default {
nameAsyn({commit}, {age, name}) {
commit(types.SET_NAME, name);
commit(types.SET_AGE, age);
}
};
複製程式碼
modules/m1.js示例,m2同理。(如果不是很複雜的應用,一般來講是不會分模組的):
export default {
state: {},
getters: {},
mutations: {},
actions: {}
};
複製程式碼
modules/indes.js,將modules檔案集中管理,如下:
import m1 from './m1';
import m2 from './m2';
export default {
m1,
m2
}
複製程式碼
index.js示例(組裝vuex):
// 如果專案中,使用的狀態管理操作非常頻繁,可以將狀態管理的物件進行細分,最後彙集之後集中管理;
import vue from 'vue'
import vuex from 'vuex'
import state from './state'
import * as getters from './getters'
import mutations from './mutations'
import actions from './actions'
import modules from './modules'
vue.use(vuex)
export default new vuex.Store({
state,
getters,
mutations,
actions,
modules
})
複製程式碼
最後將store例項掛載到main.js裡面的vue上去就行了
import store from './store';
new Vue({
el: '#app',
store,
render: h => h(App)
});
複製程式碼
在vue元件中使用時,我們通常會使用mapGetters、mapActions、mapMutations,然後就可以按照vue呼叫methods和computed的方式去呼叫這些變數或函式,示例如下:
import {mapGetters, mapMutations, mapActions} from 'vuex';
/* 只寫元件中的script部分 */
export default {
computed: {
...mapGetters([
name,
age
])
},
methods: {
...mapMutations({
setName: 'SET_NAME', // 對映 this.setName() 為 this.$store.commit('SET_NAME')
setAge: 'SET_AGE'
}),
...mapActions([
nameAsyn // 將 this.nameAsyn() 對映為 this.$store.dispatch('increment')
])
}
};
複製程式碼
mapGetters,mapMutations,mapActions的使用,相當與將已經定義好的狀態管理資料(變數,函式)引用到vue物件的computed和methods中,我們在頁面中,只管使用就行;使用方式,如: 獲取computed中的變數:
this.name;
this.age;
複製程式碼
獲取methods中的變數:
this.setName(this.name);// 對映為 `this.$store.commit('setName', this.name)`
this.setAge();
this.nameAsyn();
複製程式碼
總結:
1、如果專案中,使用的狀態管理操作非常頻繁,可以將狀態管理的物件進行細分,如區分不同的物件資料夾(state,getters,mutations,actions,modules),最後彙集之後集中管理;
2、如果專案中使用的狀態管理的變數較少時,可以採用一個檔案進行集中管理;
vuex專案整理,請參照:vue2-plugs-demo專案中src/store 和 src/store2部分;
async/await:非同步神器來封裝介面請求檔案fetch.js
在前後端分離的專案開發中,前端人員如果要通過介面獲取後端資料時,我們一般會獨立封裝自己的介面非同步請求方法,以便在整個專案中都能夠輕鬆的進行引用;
專案中使用async/await 來處理非同步請求,封裝的方法(utils/fetch.js)如下:
export default async (url = '', data = {}, type = 'POST', method = 'fetch') => {
type = type.toUpperCase()
// get請求需要進行url和引數的重新拼接
if (type === 'GET') {
let dataStr = ''
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&'
})
if (dataStr !== '') {
dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'))
url = url + '?' + dataStr
}
}
// 如果支援fecth語法(es7語法)並且請求方式為'fetch'
if (window.fetch && method === 'fetch') {
let requestConfig = {
credentials: 'include',
method: type,
headers: {
'Accept': 'application/json;charset=UTF-8',
'Content-Type': 'application/json;charset=UTF-8'
},
mode: 'cors',
cache: 'force-cache'
}
// 'POST'請求,將相關的請求引數新增到'body'中。
if (type === 'POST') {
Object.defineProperty(requestConfig, 'body', {
value: JSON.stringify(data)
})
}
// await fetch,以同步的方式將資料(json形式)進行返回,前端通過變數接收即可;
try {
const response = await fetch(url, requestConfig)
const responseJson = await response.json()
return responseJson
} catch (error) {
throw new Error(error)
}
} else { // 如果先瀏覽器不支援fetch語法,則用es6中promise()來封裝非同步介面請求;
return new Promise((resolve, reject) => {
let requestObj
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest()
} else {
let ActiveXObject = window.ActiveXObject
requestObj = new ActiveXObject()
}
let sendData = ''
if (type === 'POST') {
sendData = JSON.stringify(data)
}
requestObj.open(type, url, true)
requestObj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
requestObj.send(sendData)
requestObj.onreadystatechange = () => {
if (requestObj.readyState === 4) {
if (requestObj.status === 200) {
let obj = requestObj.response
if (typeof obj !== 'object') {
console.log(obj)
obj = JSON.parse(obj)
}
resolve(obj)
} else {
reject(requestObj)
}
}
}
})
}
}
複製程式碼
如登入介面的用到的api,統一管理在login/api/index.js中,如下:
import fetch from "@/utils/fetch";
/**
* 登入
*/
export const login = (reqData) => fetch("/v2/cotton/user/app_login", reqData);
複製程式碼
api統一管理完成之後,我們需要在頁面中進行呼叫,獲取資料,方法如下:
import { getyancode, login } from "./api";
methods: {
async login() {
// 提交時,做驗證;
if (this.checkMobile() && this.checkMsgCode()) {
this.loading.show = true;
let reqData = {
phone: mutils.replaceAllSpace(this.telphone),
code: mutils.replaceAllSpace(this.yancode)
};
try{ // try{}catch(){}用於處理異常
const res = await login(reqData);
if (res.status.code == "200") {
console.log('介面請求成功~');
} else {
console.log('介面請求失敗~');
}
}catch(err){
console.log(err)
}
}
}
}
複製程式碼
通過非同步介面請求,我們就可以獲取到相關的資料,開始後續的操作了。 非同步介面請求封裝方式分析: async/ await來傳送非同步請求,從服務端獲取資料,程式碼很簡潔,同時async/await 已經被標準化。 async的用法,它作為一個關鍵字放到函式前面,用於表示函式是一個非同步函式,也就意味著該函式的執行不會阻塞後面程式碼的執行。如:
async function timeout() {
return 'hello world'
}
timeout();
console.log('雖然在後面,但是我先執行');
複製程式碼
async 函式返回的是一個promise 物件,如果要獲取到promise 返回值,我們應該用then 方法,如:
async function timeout() {
return 'hello world'
}
timeout().then(result => {
console.log(result);
})
console.log('雖然在後面,但是我先執行');
複製程式碼
執行結果:
雖然在後面,但是我先執行
hello world
複製程式碼
async和await結合使用,await表示等待的意思,注意await 關鍵字只能放到async 函式裡面。現在寫一個函式,讓它返回promise 物件,該函式的作用是2s 之後讓數值乘以2。
// 2s 之後返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
} )
}
複製程式碼
現在再寫一個async 函式,從而可以使用await 關鍵字, await 後面放置的就是返回promise物件的一個表示式,所以它後面可以寫上 doubleAfter2seconds 函式的呼叫。
async function testResult() {
let result = await doubleAfter2seconds(30);
console.log(result);
}
複製程式碼
現在呼叫testResult 函式
testResult();
結果為:60
複製程式碼
當然我們在使用async/await來介面請求時,需要進行異常處理。它用的是try/catch 來捕獲異常,把await 放到 try 中進行執行,如有異常,就使用catch 進行處理。
fetch.js檔案整理,請參照:vue2-plugs-demo專案中utils/fetch.js 和 src/login部分;
vue 專案中的迭代判斷技巧
比如我們有一個列表,我們希望能顯示我們當前選中的那一個,如何實現呢? 基本思路是通過$index來判斷是否是當前迭代物件,然後去增減class或者style來實現不同的樣式。
<template>
<ul>
<!-- 方法1 class-->
<li v-for="item in list" :class="{'active': $index === activeId}">{{item}}</li>
<!-- 方法2 style-->
<li v-for="item in list" :style="{backgroundColor: $index === activeId ? 'red' : 'white'}">{{item}}</li>
</ul>
</template>
<script>
data () {
return {
list: ['a', 'b', 'c'],
activeId: 0
}
}
</script>
複製程式碼
vue 專案中常用的圖片引入方式
- 在img標籤中使用圖片
data () {
return {
img: require('path/to/your/source')
}
}
複製程式碼
然後在template中:
<img :src="img" />
複製程式碼
- 以背景圖的方式使用圖片
data () {
return {
img: require('path/to/your/source')
}
}
<div :style="{backgroundImage: 'url(' + img + ')'}"></div>
或者直接在css中定義
background-image: url('path/to/your/source');
複製程式碼
微信api在vue專案中的使用:
- vue2實現微信分享坑點和經驗 ;
當然要進行微信公眾號開發,前期是要經過使用者註冊並繫結相關的賬號,才會得到微信官網給出的相關的許可權,才可以進行後續的開發流程及api的呼叫,主體步驟請參見微信公眾號技術文件。我在這裡,只是介紹註冊流程走完之後,如何進行api的呼叫。
由於在做微信公眾號vue2.0前端專案開發,根據產品需要,專案中有一些自定義分享的功能和設計;由於微信自帶的分享是一個比較普通,是以它自己的分享機制,只是對某個頁面進行通常的呈現。自定義分享,就需要我們呼叫微信分享api,進行自定義配置。
分享到微信好友和QQ好友,效果如圖:
分享到微信朋友圈,效果如圖:
開發步驟如下:
1、在index.html中引入jweixin-1.2.0.js;
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
複製程式碼
2、相關微信api配置檔案utils/wx.js,如下:
import fetch from "./fetch";
/**
* baseUrl:伺服器地址
* shareOosImg:分享預設的圖示
* wechatId:申請成功的wechatId
**/
import { baseUrl,shareOosImg,wechatId } from "@/utils/env";
/**
* 獲取微信端簽名,時間戳等資訊
*/
export const getCompactHouseList = (reqData) => fetch("/v2/cotton/user/get_wechat_authorize", reqData);
export function setWxConfig(link, title, desc, pic) {
let url = window.location.href.split("#")[0];
// 公眾號申請流程走完之後,官方會給給出一個"wechatId",通過這個引數去請求我們的後臺介面,就會得到相關已經配置好的資訊。
getCompactHouseList({ "wechatId": wechatId, "url": url }).then((res) => {
if (res.status.code == 200) {
let wxConfigObj = res.result.parment;
let myLink = link ? link : "";
let myTitle = title ? title : "小愛科技";
let Mydesc = desc ? desc : "驚喜多多!優惠多多!";
let mypic = pic ? pic : shareOosImg;
wxConfig(wxConfigObj, myLink, myTitle, Mydesc, mypic);
}
}).catch((err) => {
console.log(err);
});
};
function wxConfig(wxConfigObj, link, title, desc, pic) {
// 進行初始化配置。
wx.config({
debug: false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
appId: wxConfigObj.appid, // 必填,公眾號的唯一標識
timestamp: wxConfigObj.timestamp, // 必填,生成簽名的時間戳
nonceStr: wxConfigObj.noncestr, // 必填,生成簽名的隨機串
signature: wxConfigObj.signature, // 必填,簽名
jsApiList: ["checkJsApi","onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ","chooseWXPay", "chooseImage" ] // 必填,需要使用的JS介面列表
});
wx.ready(() => {
//分享到朋友圈
wx.onMenuShareTimeline({
title: title, // 分享標題
link: link, // 分享連結,該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
imgUrl: pic, // 分享圖示
success: function () {
// alert("分享朋友圈成功");
}
});
// 分享給微信朋友
wx.onMenuShareAppMessage({
title: title, // 分享標題
desc: desc, // 分享描述
link: link, // 分享連結,該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
imgUrl: pic, // 分享圖示
type: "", // 分享型別,music、video或link,不填預設為link
dataUrl: "", // 如果type是music或video,則要提供資料連結,預設為空
success: function () {
// 使用者點選了分享後執行的回撥函式
//alert("分享朋友成功");
}
});
// 分享到QQ
wx.onMenuShareQQ({
title: title, // 分享標題
desc: desc, // 分享描述
link: link, // 分享連結
imgUrl: pic, // 分享圖示
success: function () {
// 使用者確認分享後執行的回撥函式
},
cancel: function () {
// 使用者取消分享後執行的回撥函式
}
});
wx.checkJsApi({
jsApiList: ['chooseImage'], // 需要檢測的JS介面列表,所有JS介面列表見附錄2,
success: function(res) {
console.log(res);
// 以鍵值對的形式返回,可用的api值true,不可用為false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
}
});
});
wx.error(() => {
});
};
export function chooseWXPay(data, This) {// 支付
wx.chooseWXPay({
timestamp: data.timeStamp, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp欄位均為小寫。但最新版的支付後臺生成簽名使用的timeStamp欄位名需大寫其中的S字元
nonceStr: data.nonceStr, // 支付簽名隨機串,不長於 32 位
package: data.package, // 統一支付介面返回的prepay_id引數值,提交格式如:prepay_id=\*\*\*)
signType: data.signType, // 簽名方式,預設為'SHA1',使用新版支付需傳入'MD5'
paySign: data.paySign, // 支付簽名
success: function (res) {
This.$router.push({ path: "/myReserve", query: { "reserve": "reservation" } });
}
});
};
//拍照或從手機相簿中選圖介面
export function chooseImage(callback) {
wx.chooseImage({
count: 6, // 預設9
sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,預設二者都有
sourceType: ['album', 'camera'], // 可以指定來源是相簿還是相機,預設二者都有
success: function (res) {
callback(res);
}
});
}
複製程式碼
3、在main.js中引用如下:
import Vue from "vue";
import * as wx "@/utils/wx";
Vue.use(wx);
複製程式碼
3、頁面中引用分享方法
**注意:**如果這個頁面,我們希望分享出去的內容,是按產品設計的內容,就需要在 方法中呼叫分享方法;如果我們不關心這個頁面的分享的內容,我們可以不用呼叫配置好的分享方法,預設為微信自帶的分享。
this.wx.setWxConfig(`${baseUrl}/tuijianDetail`,"我在小愛科技等你來~","驚喜多多!優惠多多!推薦好友關注有紅包~");
複製程式碼
這樣使用微信右上角的分享功能,成功分享出去之後,就可以看到想要的內容了。
- vue2實現微信支付坑點和經驗;
同理,微信支付,需要調取微信支付api。由於微信支付api,是在我們點選按鈕時觸發,所有就不需要寫在 wx.ready(() => {})裡面了。
- 相同的方法定義wx.js中:
export function chooseWXPay(data, This) {// 支付
wx.chooseWXPay({
timestamp: data.timeStamp, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp欄位均為小寫。但最新版的支付後臺生成簽名使用的timeStamp欄位名需大寫其中的S字元
nonceStr: data.nonceStr, // 支付簽名隨機串,不長於 32 位
package: data.package, // 統一支付介面返回的prepay_id引數值,提交格式如:prepay_id=\*\*\*)
signType: data.signType, // 簽名方式,預設為'SHA1',使用新版支付需傳入'MD5'
paySign: data.paySign, // 支付簽名
success: function (res) {
This.$router.push({ path: "/myReserve", query: { "reserve": "reservation" } });
}
});
};
複製程式碼
- 頁面中呼叫如下:
this.wx.chooseWXPay(res.result.list,This);
複製程式碼
支付成功之後,通過路由跳轉到其他頁面;
**注意:**微信api的成功驗證,必須要外網地址(能夠訪問的伺服器地址),如果使用自己本機的地址,放到手機上測試,是無法成功的。
百度地圖api在vue專案中的使用:
由於最近專案的開發中,要使用到地圖進行相關的城市區域,區域中房源資料的顯示,因此選擇了使用百度地圖。
百度地圖JavaScript API是一套由JavaScript語言編寫的應用程式介面,可幫助您在網站中構建功能豐富、互動性強的地圖應用,支援PC端和移動端基於瀏覽器的地圖應用開發,且支援HTML5特性的地圖開發。 百度地圖JavaScript API支援HTTP和HTTPS,免費對外開放,可直接使用。介面使用無次數限制。
- vue2.0專案中如何使用百度地圖api
使用api之前,要註冊百度賬號,申請成為百度開發者,獲取服務金鑰(ak),才能使用相關的服務功能。
開發步驟如下:
1、申請百度賬號和ak,點我申請
2、準備頁面 根據HTML標準,每一份HTML文件都應該宣告正確的文件型別,我們建議您使用最新的符合HTML5規範的文件宣告:
<!DOCTYPE html>
複製程式碼
3、適應移動端頁面展示
下面我們新增一個meta標籤,以便使您的頁面更好的在移動平臺上展示。
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
複製程式碼
4、設定容器樣式 設定容器樣式大小,使地圖充滿整個瀏覽器視窗:
<style type="text/css">
html{height:100%}
body{height:100%;margin:0px;padding:0px}
#container{height:100%}
</style>
複製程式碼
5、在index.html中引用百度地圖API檔案
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=您的金鑰"></script>
複製程式碼
6、建立地圖容器元素 地圖需要一個HTML元素作為容器,這樣才能展現到頁面上。這裡我們建立了一個div元素。
<div id="container"></div>
複製程式碼
7、建立地圖例項 位於BMap名稱空間下的Map類表示地圖,通過new操作符可以建立一個地圖例項。其引數可以是元素id也可以是元素物件。
var map = new BMap.Map("container");
複製程式碼
8、設定中心點座標
var point = new BMap.Point(116.404, 39.915);
複製程式碼
9、地圖初始化,同時設定地圖展示級別 在建立地圖例項後,我們需要對其進行初始化,BMap.Map.centerAndZoom()方法要求設定中心點座標和地圖級別。 地圖必須經過初始化才可以執行其他操作。
map.centerAndZoom(point, 15);
複製程式碼
至此,我們就快速建立了一張以天安門為中心的地圖~
- vue2如何給地圖新增房源覆蓋物;
如圖:
我們需要地圖初始化完成之後,自定義相關的方法,來新增覆蓋物;
根據官方文件,自定義標註或地圖覆蓋物。具體的實現程式碼,大家可以根據官方api進行開發。
1、定義建構函式並繼承Overlay 首先您需要定義自定義覆蓋物的建構函式,通過建構函式引數可以傳遞一些自由的變數。設定自定義覆蓋物物件的prototype屬性為Overlay的例項,以便繼承覆蓋物基類。
// 定義自定義覆蓋物的建構函式
function SquareOverlay(center, length, color){
this._center = center;
his._length = length;
this._color = color;
}
// 繼承API的BMap.Overlay
SquareOverlay.prototype = new BMap.Overlay();
複製程式碼
2、初始化自定義覆蓋物
實現initialize方法,當呼叫map.addOverlay方法時,API會呼叫此方法。 當呼叫map.addOverlay方法新增自定義覆蓋物時,API會呼叫該物件的initialize方法用來初始化覆蓋物,在初始化過程中需要建立覆蓋物所需要的DOM元素,並新增到地圖相應的容器中。這裡我們選擇新增在容器markerPane上。
// 實現初始化方法
SquareOverlay.prototype.initialize = function(map){
// 儲存map物件例項
his._map = map;
// 建立div元素,作為自定義覆蓋物的容器
var div = document.createElement("div");
div.style.position = "absolute";
// 可以根據引數設定元素外觀
div.style.width = this._length + "px";
div.style.height = this._length + "px";
div.style.background = this._color;
// 將div新增到覆蓋物容器中
map.getPanes().markerPane.appendChild(div);
// 儲存div例項
this._div = div;
// 需要將div元素作為方法的返回值,當呼叫該覆蓋物的show、
// hide方法,或者對覆蓋物進行移除時,API都將操作此元素。
return div;
}
複製程式碼
3、繪製覆蓋物
實現draw方法。 到目前為止,我們僅僅把覆蓋物新增到了地圖上,但是並沒有將它放置在正確的位置上。 您需要在draw方法中設定覆蓋物的位置,每當地圖狀態發生變化(比如:位置移動、級別變化)時,API都會呼叫覆蓋物的draw方法,用於重新計算覆蓋物的位置。 通過map.pointToOverlayPixel方法可以將地理座標轉換到覆蓋物的所需要的畫素座標。
// 實現繪製方法
SquareOverlay.prototype.draw = function(){
// 根據地理座標轉換為畫素座標,並設定給容器
var position = this._map.pointToOverlayPixel(this._center);
this._div.style.left = position.x - this._length / 2 + "px";
this._div.style.top = position.y - this._length / 2 + "px";
}
複製程式碼
4、移除覆蓋物 當呼叫map.removeOverlay或者map.clearOverlays方法時,API會自動將initialize方法返回的DOM元素進行移除。
map.removeOverlay();
複製程式碼
5、新增覆蓋物 您現在已經完成了一個完整的自定義覆蓋物的編寫,可以新增到地圖上了。
// 初始化地圖
var map = new BMap.Map("container");
var point = new BMap.Point(116.404, 39.915);
map.centerAndZoom(point, 15);
// 新增自定義覆蓋物
var mySquare = new SquareOverlay(map.getCenter(), 100, "red");
map.addOverlay(mySquare);
複製程式碼
- 如何給地圖新增自定義定位控制元件並更換控制元件的圖示;
給地圖新增自定義控制元件,需要用到控制元件類:ZoomControl,使用方法如下:
addControlLocation(){
var that = this;
// 定義一個控制元件類,即function
function ZoomControl(){
// 設定預設停靠位置和偏移量
this.defaultAnchor = BMAP_ANCHOR_BOTTOM_LEFT;
this.defaultOffset = new BMap.Size(20, 50);
}
// 通過JavaScript的prototype屬性繼承於BMap.Control
ZoomControl.prototype = new BMap.Control();
ZoomControl.prototype.initialize = function(map){
// 建立一個DOM元素
var img = document.createElement("img");
img.setAttribute('src',that.locationImg)
// 設定樣式
img.style.cursor = "pointer";
// 繫結事件,獲取當前城市
img.onclick = function(e){... }
// 新增DOM元素到地圖中
map.getContainer().appendChild(img);
// 將DOM元素返回
return img;
}
// 建立控制元件例項
var myZoomCtrl = new ZoomControl();
// 新增到地圖當中
this.mp.addControl(myZoomCtrl);
}
複製程式碼
在地圖初始化完成後,呼叫addControlLocation()方法即可;
- 新增自定義 當前位置定位標註
如圖:
需要用到new BMap.Marker();設定圖示大小用 myIcon.setImageSize();
addCurrentMarker(){ // 新增自定義 當前位置定位標註
var myIcon = new BMap.Icon(this.redLocation,{
offset: new BMap.Size(10, 25), // 指定定位位置
imageOffset: new BMap.Size(0, 0 - 10 * 25) // 設定圖片偏移
});
// myIcon.setStyle({width: '.666rem', height: '.666rem'});
myIcon.setImageSize(new BMap.Size(60,60)); // 設定 圖示大小
let point = new BMap.Point(this.currentPoint.lng,this.currentPoint.lat); // 標註的中心點,應該是始終是使用者當前位置
let marker = new BMap.Marker(point,{icon:myIcon}); // 建立Marker標註
this.mp.addOverlay(marker); // 新增當前定位點
},
複製程式碼
- 幾個常用的api(地圖縮放,拖拽,獲取當前位置)等功能的實現;
- 地圖表面觸發點選事件:
this.mp.addEventListener("touchstart", () => {});
複製程式碼
- 地圖縮放事件:
this.mp.addEventListener("zoomend", () => {});
複製程式碼
- 地圖拖拽事件:
this.mp.addEventListener("dragstart",()=>{});
this.mp.addEventListener("dragend",()=>{});
複製程式碼
- 獲取使用者當前位置(經緯度物件):
export function getLocationData(fn) {
let geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(function (r) {
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
fn(r.point);
}
});
}
複製程式碼
- 根據經緯度解析地址資訊,分別返回省市區街等:
let gc = new BMap.Geocoder();//Geocoder地址編碼
gc.getLocation(item, function (rs) { //getLocation函式用來解析地址資訊,分別返回省市區街等 r.point裡有經緯度
let addComp = rs.addressComponents;
let province = addComp.province;//獲取省份
let city = addComp.city;//獲取城市
});
複製程式碼
專案實踐:基於vue2.0 +vuex+ element-ui後臺管理系統
歡迎加入討論組,一起來學習用vue,vuex,element,express,mongodb來構建後臺管理系統;
一起來用專案實戰加深自己對知識的理解。