最近一直在作移動端微信公衆號項目的開發,也是我首次用vue來開發移動端項目,前期積累的移動端開發經驗較少。通過這個項目的鍛鍊,加深了對vue相關知識點的理解和運用,同時,在項目中所涉及到的微信api(微信分享,微信支付),百度地圖api(如何實例化地圖,給地圖添加自定義覆蓋物,給地圖添加自定義標註,對地圖進行縮放,拖拽等)的相關使用,開闊了本身的知識眼界;現將我開發過程當中積累的相關經驗與你們進行分享,但願和你們一塊兒學習和進步....javascript
vux:Vue 移動端 UI 組件庫的使用;php
vue-lazyload :一個簡單易用的 Vue 圖片延遲加載插件;css
vuex:vue狀態管理工具詳細入門;html
async/await:異步神器來封裝接口請求文件fetch.js前端
vue 項目中的迭代判斷技巧;vue
vue 項目中經常使用的圖片引入方式;java
微信api在vue項目中的使用:webpack
vue2實現微信分享坑點和經驗 ;git
vue2實現微信支付坑點和經驗;es6
百度地圖api在vue項目中的使用:
vue2.0項目中如何使用百度地圖api
vue2如何給地圖添加房源覆蓋物;
如何給地圖添加自定義定位控件並更換控件的圖標;
如何給地圖添加自定義當前位置定位標註
幾個經常使用的api(地圖縮放,拖拽,獲取當前位置)等功能的實現;
vux介紹:詳細請參見官方文檔。
因爲是作微信公衆號移動端項目,咱們對比了幾個vuejs的移動端UI庫,知道vux是基於WeUI和Vue(2.x)開發的移動端UI組件庫,主要服務於微信頁面;雖然它屬於我的維護,體驗上須要一些改進。但項目中幾個組件的使用,大大提高了開發效率。
使用方法以下:
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']
})
複製代碼
若是你要使用的組件只是在當前頁面中使用,咱們能夠只在當前頁面中引入便可。若是在不少頁面中都有使用,能夠在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-lazyload主要應用於圖片延遲加載。包含以下的特色:
理解圖片延遲加載:
當某個網頁中呈現的圖片較多時,因爲網絡等緣由,訪問該網頁時,全部的圖片不會立馬所有進行顯示出來,會出現必定的網絡延遲加載的現象,影響用戶體驗;但咱們能夠vue-lazyload插件來實如今圖片加載的過程當中,先顯示出默認的加載圖片,直到圖片徹底顯示,默認圖片消失,這樣就會大大的提高用戶體驗。
使用方法以下:
一、經過npm安裝
npm install vue-lazyload -s
複製代碼
二、在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 // 圖像嘗試加載 次數
})
複製代碼
三、在組件中使用
<img v-lazy="item.picUrl" alt="">
複製代碼
四、實現效果之後,還能夠根據API進行功能擴展。
相應的參數可參考官方API進行設置。
五、vue-lazyLoad文件整理,請參照:vue2-plugs-demo項目中src/components/LazyLoad/index.vue 和 src/main.js部分;;
詳細介紹請參見官方網站。Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 什麼狀況下我應該使用 Vuex? 若是您須要構建一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。 使用方法:
npm install vuex --save
複製代碼
import Vuex from "vuex";
Vue.use(Vuex);
複製代碼
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來進行實際的開發,在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();
複製代碼
一、若是項目中,使用的狀態管理操做很是頻繁,能夠將狀態管理的對象進行細分,如區分不一樣的對象文件夾(state,getters,mutations,actions,modules),最後聚集以後集中管理;
二、若是項目中使用的狀態管理的變量較少時,能夠採用一個文件進行集中管理;
vuex項目整理,請參照:vue2-plugs-demo項目中src/store 和 src/store2部分;
在先後端分離的項目開發中,前端人員若是要經過接口獲取後端數據時,咱們通常會獨立封裝本身的接口異步請求方法,以便在整個項目中都可以輕鬆的進行引用;
項目中使用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部分;
好比咱們有一個列表,咱們但願能顯示咱們當前選中的那一個,如何實現呢? 基本思路是經過$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>
複製代碼
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的調用,主體步驟請參見微信公衆號技術文檔。我在這裏,只是介紹註冊流程走完以後,如何進行api的調用。
因爲在作微信公衆號vue2.0前端項目開發,根據產品須要,項目中有一些自定義分享的功能和設計;因爲微信自帶的分享是一個比較普通,是以它本身的分享機制,只是對某個頁面進行一般的呈現。自定義分享,就須要咱們調用微信分享api,進行自定義配置。
分享到微信好友和QQ好友,效果如圖:
分享到微信朋友圈,效果如圖:
開發步驟以下:
一、在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>
複製代碼
二、相關微信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);
}
});
}
複製代碼
三、在main.js中引用以下:
import Vue from "vue";
import * as wx "@/utils/wx";
Vue.use(wx);
複製代碼
三、頁面中引用分享方法
**注意:**若是這個頁面,咱們但願分享出去的內容,是按產品設計的內容,就須要在 方法中調用分享方法;若是咱們不關心這個頁面的分享的內容,咱們能夠不用調用配置好的分享方法,默認爲微信自帶的分享。
this.wx.setWxConfig(`${baseUrl}/tuijianDetail`,"我在小愛科技等你來~","驚喜多多!優惠多多!推薦好友關注有紅包~");
複製代碼
這樣使用微信右上角的分享功能,成功分享出去以後,就能夠看到想要的內容了。
同理,微信支付,須要調取微信支付api。因爲微信支付api,是在咱們點擊按鈕時觸發,全部就不須要寫在 wx.ready(() => {})裏面了。
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的成功驗證,必需要外網地址(可以訪問的服務器地址),若是使用本身本機的地址,放到手機上測試,是沒法成功的。
因爲最近項目的開發中,要使用到地圖進行相關的城市區域,區域中房源數據的顯示,所以選擇了使用百度地圖。
百度地圖JavaScript API是一套由JavaScript語言編寫的應用程序接口,可幫助您在網站中構建功能豐富、交互性強的地圖應用,支持PC端和移動端基於瀏覽器的地圖應用開發,且支持HTML5特性的地圖開發。 百度地圖JavaScript API支持HTTP和HTTPS,免費對外開放,可直接使用。接口使用無次數限制。
使用api以前,要註冊百度帳號,申請成爲百度開發者,獲取服務密鑰(ak),才能使用相關的服務功能。
開發步驟以下:
一、申請百度帳號和ak,點我申請
二、準備頁面 根據HTML標準,每一份HTML文檔都應該聲明正確的文檔類型,咱們建議您使用最新的符合HTML5規範的文檔聲明:
<!DOCTYPE html>
複製代碼
三、適應移動端頁面展現
下面咱們添加一個meta標籤,以便使您的頁面更好的在移動平臺上展現。
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
複製代碼
四、設置容器樣式 設置容器樣式大小,使地圖充滿整個瀏覽器窗口:
<style type="text/css">
html{height:100%}
body{height:100%;margin:0px;padding:0px}
#container{height:100%}
</style>
複製代碼
五、在index.html中引用百度地圖API文件
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=您的密鑰"></script>
複製代碼
六、建立地圖容器元素 地圖須要一個HTML元素做爲容器,這樣才能展示到頁面上。這裏咱們建立了一個div元素。
<div id="container"></div>
複製代碼
七、建立地圖實例 位於BMap命名空間下的Map類表示地圖,經過new操做符能夠建立一個地圖實例。其參數能夠是元素id也能夠是元素對象。
var map = new BMap.Map("container");
複製代碼
八、設置中心點座標
var point = new BMap.Point(116.404, 39.915);
複製代碼
九、地圖初始化,同時設置地圖展現級別 在建立地圖實例後,咱們須要對其進行初始化,BMap.Map.centerAndZoom()方法要求設置中心點座標和地圖級別。 地圖必須通過初始化才能夠執行其餘操做。
map.centerAndZoom(point, 15);
複製代碼
至此,咱們就快速建立了一張以天安門爲中心的地圖~
如圖:
咱們須要地圖初始化完成以後,自定義相關的方法,來添加覆蓋物;
根據官方文檔,自定義標註或地圖覆蓋物。具體的實現代碼,你們能夠根據官方api進行開發。
一、定義構造函數並繼承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();
複製代碼
二、初始化自定義覆蓋物
實現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;
}
複製代碼
三、繪製覆蓋物
實現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";
}
複製代碼
四、移除覆蓋物 當調用map.removeOverlay或者map.clearOverlays方法時,API會自動將initialize方法返回的DOM元素進行移除。
map.removeOverlay();
複製代碼
五、添加覆蓋物 您如今已經完成了一個完整的自定義覆蓋物的編寫,能夠添加到地圖上了。
// 初始化地圖
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); // 添加當前定位點
},
複製代碼
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來構建後臺管理系統;
一塊兒來用項目實戰加深本身對知識的理解。