Ionic使用百度地图弹窗并响应点击事件

1,258 5分钟

Ionic响应百度地图弹窗中的点击事件:
Ionic使用的语法TypeScript,有一套自己的生命周期,和ES5之前的使用习惯不相同,变量作用域不尽相同。在Ionic中使用百度地图,也会踩一些坑,最近在业务中遇到了这样的需求,百度地图弹窗中动态写的HTML布局的响应事件无法拿到。

在Ionic中使用百度地图

初始化地图

1
2
3
4
5
6
7
8
9
// 1.首先在index.html中引入百度地图的URL(其中要有申请的KEY)
// <script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=您的密钥"></script>

// 2.新建map组件,在ts文件中输入以下内容
ionViewWillEnter(){
let map = new BMap.Map("allmap");// allmap是在html布局中定义的<div id="allmap"></div>
let point = new BMap.Point(116.417, 39.921);// 初始化地图
map.centerAndZoom(point, 15);// 初始化地图视图
}

添加Marker

1
2
3
// 3.在 map.centerAndZoom(point, 15) 的下一行继续添加以下内容
let marker = new BMap.Marker(point);// 初始化Marker对象
map.addOverlay(marker);// 将marker放置到地图上

为marker添加点击事件

1
2
3
4
// 4.在 map.addOverlay(marker) 的下一行继续添加以下内容
marker.addEventListener("click", function(){
// TODO 做其他事情
});

弹出信息窗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 5.在 map.addOverlay(marker) 和 marker.addEventListener 之间插入以下内容
let options = {
width: 200,
height: 100,
title: "测试弹窗的标题"
}; // 定义弹出窗参数
let htm = '<div>内容:这是内容主体</div><div><button id="confirm" onclick="test()">确定</button></div>';
let infoWindow = new BMap.InfoWindow(htm, options); // 初始化弹出窗对象

// 6.在 TODO 下面继续添加以下内容
map.openInfoWindow(infoWindow, point); // 点击marker执行该行代码,弹出信息窗

// 7.在该ts文件中,添加test方法
test(){
console.log("如果我再控制台中打印出来,说明弹窗中的button响应了,反之。");
}

控制台没打印

打印失败了!!!

有人分析说,test需要用this来调用,写成这个样子

1
let infoWindow = new BMap.InfoWindow('<div>内容:这是内容主体,啦啦啦</div><div><button id="confirm" onclick="this.test()">确定</button></div>', options); // 初始化弹出窗对象

同样的,还是失败了。

分析原因,是Ionic在初始化页面时,弹窗的布局信息并没有跟着初始化,而绑定的test()方法也没有初始化,所以绑定的方法无效。

解决方法

那怎么样才能保证能将test()方法绑定到button上的呢?

其实,我们可以曲线救国,让绑定事件在初始化弹窗之后,弹窗之前绑定,这样既可以有效的防止页面初始化带来的影响,又可以顺利绑定事件,下面是我的做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 以上完整代码
// 1.首先在index.html中引入百度地图的URL(其中要有申请的KEY)
// <script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=您的密钥"></script>

// 2.新建map组件,在ts文件中输入以下内容
ionViewWillEnter(){
let map = new BMap.Map("allmap");// allmap是在html布局中定义的<div id="allmap"></div>
let point = new BMap.Point(116.417, 39.921);// 初始化地图
map.centerAndZoom(point, 15);// 初始化地图视图

// 3.在 map.centerAndZoom(point, 15) 的下一行继续添加以下内容
let marker = new BMap.Marker(point);// 初始化Marker对象
map.addOverlay(marker);// 将marker放置到地图上

// 5.在 map.addOverlay(marker) 和 marker.addEventListener 之间插入以下内容
let options = {
width: 200,
height: 100,
title: "测试弹窗的标题"
}; // 定义弹出窗参数
let htm = '<div>内容:这是内容主体</div><div><button id="confirm">确定</button></div>';
let infoWindow = new BMap.InfoWindow(htm, options); // 初始化弹出窗对象

// 4.在 map.addOverlay(marker) 的下一行继续添加以下内容
let that = this;
marker.addEventListener("click", function(){
// TODO 做其他事情
// 绑定监听事件
document.getElementById("confirm").onclick = that.test;
map.openInfoWindow(infoWindow, point); // 点击marker执行该行代码,弹出信息窗
});
}

// 7.在该ts文件中,添加test方法
test(){
console.log("如果我再控制台中打印出来,说明弹窗中的button响应了,反之。");
}

这样子再测试的话,控制台中就可以打印如果我再控制台中打印出来,说明弹窗中的button响应了,反之。

总结

以上问题在常规的B/S项目中不会发生,这是因为在Ionic项目中,使用的是Angular语法,即TypeScript(JavaScript的超集),该语法自己定义了一些新特性,使得开发效率更高,语法更简洁,再加上ES6(或更高)新特性,使得在动态生成的页面上绑定监听事件失效,所以可以通过延迟绑定或者适当时机绑定来解决。

Ionic做项目和以往的ES5或原生项目相比,效率更高、兼容多平台、开源组件更多、也更加美观,是一个比较好的路子。


关注公众号

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器