最近一直在做移动端微信公众号项目的开发,也是我首次用vue来开发移动端项目,前期积累的移动端开发经验较少。经过这个项目的锻炼,加深了对vue相关知识点的理解和运用,同时,在项目中所涉及到的微信api(微信分享,微信支付),百度地图api(如何实例化地图,给地图添加自定义覆盖物,给地图添加自定义标注,对地图进行缩放,拖拽等)的相关使用,开阔了自己的知识眼界;现将我开发过程中积累的相关经验与大家进行分享,希望和大家一起学习和进步....

  • vux:Vue 移动端 UI 组件库的使用;

  • vue-lazyload :一个简单易用的 Vue 图片延迟加载插件;

  • vuex:vue状态管理工具详细入门;

  • async/await:异步神器来封装接口请求文件fetch.js

  • vue 项目中的迭代判断技巧;

  • vue 项目中常用的图片引入方式;

  • 微信api在vue项目中的使用:

    1. vue2实现微信分享坑点和经验 ;

    2. vue2实现微信支付坑点和经验;

  • 百度地图api在vue项目中的使用:

    1. vue2.0项目中如何使用百度地图api

    2. vue2如何给地图添加房源覆盖物;

    3. 如何给地图添加自定义定位控件并更换控件的图标;

    4. 如何给地图添加自定义当前位置定位标注

    5. 几个常用的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 项目中常用的图片引入方式

  1. 在img标签中使用图片
data () {
return {
img: require('path/to/your/source')
}
}

然后在template中:

<img :src="img" />
  1. 以背景图的方式使用图片
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实现微信分享坑点和经验 ;

官方网址:微信公众平台技术文档/微信JS-SDK说明文档

当然要进行微信公众号开发,前期是要经过用户注册并绑定相关的账号,才会得到微信官网给出的相关的权限,才可以进行后续的开发流程及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(() => {})里面了。

  1. 相同的方法定义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" } });
}
});
};
  1. 页面中调用如下:
this.wx.chooseWXPay(res.result.list,This);

支付成功之后,通过路由跳转到其他页面;

注意:微信api的成功验证,必须要外网地址(能够访问的服务器地址),如果使用自己本机的地址,放到手机上测试,是无法成功的。

百度地图api在vue项目中的使用:

官方网址示例demo参考类

由于最近项目的开发中,要使用到地图进行相关的城市区域,区域中房源数据的显示,因此选择了使用百度地图。

百度地图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(地图缩放,拖拽,获取当前位置)等功能的实现;
  1. 地图表面触发点击事件:
this.mp.addEventListener("touchstart", () => {});
  1. 地图缩放事件:
this.mp.addEventListener("zoomend", () => {});
  1. 地图拖拽事件:
this.mp.addEventListener("dragstart",()=>{});
this.mp.addEventListener("dragend",()=>{});
  1. 获取用户当前位置(经纬度对象):
export function getLocationData(fn) {
let geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(function (r) {
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
fn(r.point);
}
});
}
  1. 根据经纬度解析地址信息,分别返回省市区街等:
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来构建后台管理系统;

一起来用项目实战加深自己对知识的理解。

干货分享:vue2.0做移动端开发用到的相关插件和经验总结(2)的更多相关文章

  1. vue2.0做移动端开发用到的相关插件和经验总结1.0

    最近在用vue2.0做微信公众号相关的前端开发,经过这次开发实践,现将项目中用到的相关比较实用的插件及遇到的相关问题进行整理,希望和大家共同交流...... cssrem:一个CSS值转REM的VSC ...

  2. vue2.0做移动端开发用到的相关插件和经验总结

    最近一直在做移动端微信公众号项目的开发,也是我首次用vue来开发移动端项目,前期积累的移动端开发经验较少.经过这个项目的锻炼,加深了对vue相关知识点的理解和运用,同时,在项目中所涉及到的微信api( ...

  3. 饿了么基于Vue2.0的通用组件开发之路(分享会记录)

    Element:一套通用组件库的开发之路 Element 是由饿了么UED设计.饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库.今天我们要分享的就是开发 Element 的一些心得. 官网 ...

  4. 从架构师视角看是否该用Kotlin做服务端开发?

    前言 自从Oracle收购Sun之后,对Java收费或加强控制的尝试从未间断,谷歌与Oracle围绕Java API的官司也跌宕起伏.虽然Oracle只是针对Oracle JDK8的升级收费,并释放了 ...

  5. 基于vue2.0的分页组件开发

    今天安排的任务是写基于vue2.0的分页组件,好吧,我一开始是觉得超级简单的,但是越写越写不出来,写的最后乱七八糟的都不知道下句该写什么了,所以重新捋了思路,小结一下- 首先写组件需要考虑: 要从父组 ...

  6. vue2.0 在微信端如何使用本地IP访问项目

    我们会遇到这样的需求,在PC端开发vue脚手架项目,希望在微信端随时浏览页面(如果打包再发布到服务器又太麻烦),怎么办? 思路很简单:保证手机和电脑在同一个IP下,用同一个IP访问项目,这样就可以了: ...

  7. 基于Vue2.0的单页面开发方案

    2016的最后一天,多多少少都应该总结一下这一年的得失,哪里做的好,哪里需要改进,记一笔,或许将来会用到呢. 毕业差不多半年了,一直是一个人在负责公司项目的前端开发与维护,当时公司希望前后端分离,提高 ...

  8. Vue2.0做的项目在IE下面打开一片空白?

    解决方式:安装 "babel-polyfill" 即可. 命令:cnpm install --save-dev babel-polyfill 在入口main.js文件引入:impo ...

  9. Vue2.0 中,“渐进式框架”和“自底向上增量开发的设计”这两个概念是什么?(转)

    https://www.zhihu.com/question/51907207?rf=55052497 徐飞 在我看来,渐进式代表的含义是:主张最少. 每个框架都不可避免会有自己的一些特点,从而会对使 ...

随机推荐

  1. (网页)javascript该如何学习?怎么样才能学好?

    文章摘抄自强哥文章   很多刚刚涉足软件开发的差不多都是只懂得HTMLCSS不懂得javascript,所以就想学习js,于是就从网上搜各种视频,或者买各种书籍回来看,很多时候都是浪费时间,因为根本看 ...

  2. 逻辑回归&线性回归

    # coding:utf-8 import numpy as np from sklearn import linear_model, datasets import matplotlib.pyplo ...

  3. 【PAT】B1054 求平均值(20 分)

    一开始就想用sscanf和sprintf去实现,但是没有设计好思路,卡住了. 看了网上别人的博客,都是用的很复杂的逻辑分别判断,一言不合就七八十航代码 今天早上看了柳神的代码,发现跟自己的思路一样,开 ...

  4. January 31st, 2018 Week 05th Wednesday

    Real love is not just instinct, but intent. 真正的爱不是身体上的一见钟情,而是要用心去经营. What is real love? Honestly, I ...

  5. firefox event.preventDefault(); 没有效果的解决方案

    $('.sub-list-click a').click(function (event) { event.preventDefault(); var sub = $(this).parent(&qu ...

  6. Codeforces Round #245 (Div. 2)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/yew1eb/article/details/25609981 A Points and Segmen ...

  7. js常见错误类型

    (1)SyntaxError SyntaxError是解析代码时发生的语法错误 // 变量名错误 var 1a; // 缺少括号 console.log 'hello'); (2)ReferenceE ...

  8. Choosing number ZOJ - 3690 (矩阵快速幂)

    题意:n个人站成一排,每个人任意从1——m中任意取一个数,要求相邻两个人的如果数字相同,数字要大于k. 分划思想推导表达式: 假设  i  个人时.第i个人的选择有两种一种是选择小于等于k的数,另一种 ...

  9. RocketMQ集群部署记录

    RocketMQ集群部署记录 #引用    https://cloud.tencent.com/developer/article/1147765         一.RocketMQ基础知识介绍 A ...

  10. python基础学习第二天

    读文件 r 要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符 写文件 w 写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’或者’w ...