文章目录
前言
Hello大家好啊,写文章是一个比较好的习惯,但我却有点喜欢偷懒,导致这一篇文章在周一的时候就写了,到了周末才开始着手。之前写文章有的时候不知道题材是什么,但自从实习之后会遇到很多值得记录的业务场景。最近也在读一本书《下班后开始新的一天》,通过这本书我了解到了,可以把一天分成两天过,上班的时候工作如果能够享受这个过程是最佳的,下班之后应该享受属于自己的4个小时,可以找自己喜欢的事情、找到自己的副业。目前对我而言,写博客是蛮享受的一个过程。
最近在开发地图相关项目的时候,突然有这么一个需求:需要在添加设备的表单选择位置时弹出百度地图的组件,点击地图上的某一处返回对应的经纬度信息。且右上角需要有一个省份城市切换的控制器用来返回相应的省市信息给表单对象(对用户直接缩小地图切换省份的操作不做出省份切换)
。
这一次的业务其实是在基于vue2.0的项目,但我最近在研究vue3.0 + typescript + hooks
,因此就决定将这次的demo以v3+ts的形式编写,事实证明,这一波操作确实是将复杂度提升了一个档次,本来非常简单的逻辑现在需要考虑到地图异步加载拿不到全局对象BMap、地图组件难取得hooks中的Geocoder等问题
,有点没事找事的意思哈哈。不过核心函数代码是不区分v2、v3
的,核心函数的部分其实也就是本文的中心,并且,这个核心函数的部分还非常简单易懂。
因为完整的代码越写越觉得自己有点多此一举,因此就不在文章上分享了,更多的还是想找点vue3+typescript+hooks
搭建项目的感觉。源码地址:vue3-ts-baidu-map。
一、核心代码
那么我们直接开始,这样一个业务其实是比较简单的,实现省市选择器可以使用自定义组件 + 地图api提供的添加自定义组件
,也可以使用地图自带的城市列表控件
。相对来说使用地图自带的控件会更加容易一些且更有兼容性一些。
以下是地图api官网提供的城市列表控件Demo中的添加控件的部分代码,可以看到其中只配置了 anchor、offset两个属性。
但其实cityControl还可以配置对应的响应函数,如onChangeBefore、onChangeAfter、以及最为重要
onChangeSuccess
配置项。
通过日志打印,我们可以拿到onChangeSuccess回调函数中ev的结构。其中我们关心的数据有point中的
lng、lat
,细心的你也许发现了ev结构中的city并不符合我们的要求,因为如果选择城市则就只有城市信息、选择省份则就只有省份信息。所以需要我们的二次处理。
这里我选择的是用经纬度逆解析Geocoder
将城市列表选择得到的经纬度逆地址解析为详细地址,取得需要的省份、城市
信息。
而获取经纬度信息就比较简单了,只要用到百度地图中的marker以及给地图添加点击事件获取经纬度赋值给位置信息对象即可。
二、可能遇到的问题
还是想跟大家分享一下在做这个demo项目中我遇到的一些问题,以及目前我解决它们的办法
1、关于百度地图相关变量报错的问题
报错: TS2552: Cannot find name ‘BMap’. Did you mean ‘Map’? 或
TS2551: Property ‘BMap’ does not exist on type ‘Window & typeof globalThis’. Did you mean ‘Map’?
解决方法:
这是因为我们没有对BMap等地图相关变量进行注册,这里我解决的方法是:在src目录下创建global.d.ts
文件,并对window进行接口定义:
2、处理地图script标签异步插入完成前获取不到地图相关对象报错问题
问题:使用window.BMap、Map时报错undefined
下方图片中展示的是我将百度地图javascript标签插入body的方式,不同于直接在public/index.html
中直接插入,这里我选择了异步插入,当组件调用地图hooks中的initMap函数
就会调用createMap方法
进而将js标签插入到body中。同时我将对地图添加事件函数、地图控件的方法也抽离了出来,这样就会造成一个问题:因为相关添加的函数都是同步的,当执行时非常大可能地图script还未添加至body中,也就是window全局对象中没有地图相关变量
。
解决方法:
在这里我在外层分别定义了处理异步问题的事件栈与组件栈,并在onload的末尾加入判断异步栈中是否存在元素,存在则执行。也就是说我将添加的逻辑先缓存在了对应的栈中,当地图完成添加之后将缓存的函数拿出执行。
3、使用Ant-design-vue 想要使 <a-input />标签处于只读状态
解决方法:给标签加上readOnly属性即可
总结
以上便是本篇文章的全部内容啦,这一篇文章写了比较长的一段时间。主要是因为对于vue3 + typescript
一些写法、api的不熟悉,以及异步加载百度地图可能造成的一系列问题的解决。(吐槽:还有隔壁情侣大晚上动静比较大,好几天没有休息好再加上这周工作量的增加,比较没有心思去完整的写完这篇文章)总的来说这一次的demo对自己学习新知识还是很有帮助的,就得多写写demo,多遇到一些bug,在视频、文章中看到的知识点才能被更加深刻的吸收进脑海中。
说一个题外话,如果是在v2.x下要使用百度地图的话还是比较推荐使用 vue-baidu-map 这个插件的,大佬封装的非常完整了,只要把控件以组件的方式往template中一放,就完成了控件的添加,还是相当方便的!就是在城市列表这个组件封装的时候并没有写到onChangeSuccess
,因此没办法在标签上以@onChangeSuccess
的方式实现组件切换位置信息的返回。