参考链接
https://blog.csdn.net/qq_43067919/article/details/121032319
https://www.jianshu.com/p/57ebc0eef122
https://lbs.amap.com/api/jsapi-v2/summary
https://uniapp.dcloud.net.cn/tutorial/renderjs.html#renderjs
纯vue前端,零uniapp经验,需求让给uniapp 上的地图标记加个按钮,前人是用自带的Map组件实现的,用的高德地图,但是地图标记貌似不支持自定义啊,我寻思可能得自己实现了, 开始试了leaflet啊,没注意main.js 的css没导入成功(重新运行了才发现…),然后瓦片是错乱的, 而且接入高德地图也不方便(菜 … …兜兜转转发现高德有自带的sdk,使用效果很好啊
常规的vue单文件组件如下
可以使用npm安装 (个人推荐) ,也可以动态创建 script 方式引用
# npm 安装
npm i @amap/amap-jsapi-loader
uniapp安卓端是没有BOM DOM这套的,所以依赖canvas相关的库是用不了,官方方案就是使用 renderjs
官方解释: 使用了非H5端不支持的API 小程序和App的js运行在jscore下而不是浏览器里,没有浏览器专用的js对象,比如document、xmlhttp、cookie、window、location、navigator、localstorage、websql、indexdb、webgl等对象。vue页面通过renderjs可以操作浏览器对象,进而可以让基于浏览器的库直接在uni-app的App端运行,诸如echart、threejs
举个简单栗子
key申请地址: https://console.amap.com/dev/key/app (登录控制台新建个应用就有了)
<template>
<view id="a-map-container">
</view>
</template>
<sctipt setup>
....
</script>
<script module="AMap" lang="renderjs">
import AMapLoader from '@amap/amap-jsapi-loader';
AMapLoader.load({
"key": "68aae429918d9c1a46ba170e3xxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
"version": "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
"plugins": [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap)=>{
new AMap.Map('a-map-container');
})
export default {
// ...
methods: {
// ...
}
}
</script>
<style>
#a-map-container {
width: 100%;
height: 100%;
}
</style>
就是单文件组件后面加个script块,指定个 module 和 lang=“renderjs” 即可
如果不考虑数据交互的话module可以不指定值,反之需要指定个值用于外部访问
参考资料
逻辑层是不能直接访问到renderjs的,视图层才能访问renderjs !!
视图层标签上有个update属性,可以监听逻辑层的数据变化再操作renderjs 以间接达到逻辑层访问renderjs的目的,这语法我没见过,我在其他vue3的项目试了下不行的啊,应该是uniapp支持的,不过具体文档我也没找见…
<template>
<view id="a-map-container" :markers="tests" :change:markers="AMapInstance.reloadMarker">
</view>
</template>
<script>
import {ref} from 'vue'
export default {
setup(props) {
const markers = ref()
setTimeout(() => {
markers.value = []
}, 10)
return {
markers
}
}
}
</script>
<script module="AMap" lang="renderjs">>
export default {
methods() {
// ...
reloadMarker(dataList) {
console.log('reloadMarker', dataList);
}
},
}
</script>
运行后控制台输出
reloadMarker, undefined
reloadMarker, [Object] []
需要注意以下两点
:change
绑定的函数开始会调用一次,这次调用在vue3(setup语法糖,组合式API, 选项式API)情况下接收的非空参数会被转为JSON字符串并且前面会追加json://,另见https://ask.dcloud.net.cn/question/149521const markers = ref()
markers.value = []
注意: 这种情况也算有默认值了,所以也会导致接收的参数异常
const markers = ref()
markers.value = 1
markers.value = 2
markers.value = 3
最后只会生效3,前几次都会被忽略掉
视图层标签上有个update属性,可以监听逻辑层的数据变化再操作renderjs 以间接达到逻辑层访问renderjs的目的,这语法我没见过,我在其他vue3的项目试了下不行的啊,应该是uniapp支持的,不过具体文档我也没找见…
<template>
<view id="a-map-container" >
</view>
</template>
<script>
export default {
setup(props) {
const loaded = function(e) {
console.log('加载成功了!!', e);
}
return {
loaded
}
}
}
</script>
<script module="AMap" lang="renderjs">>
export default {
mounted() {
// ...
this.$ownerInstance.callMethod('loaded', 8888)
},
}
</script>
运行后即可看到 加载成功了!!, [Number] 8888
需要注意以下两点
$ownerInstance
需要执行到mounted时才会存在,:update
初次调用renderjs函数时机在mounted之前,所以直接在被访问的methods函数里访问逻辑层很可能直接报错的$ownerInstance.callMethod
访问的函数使用setup语法糖时无法访问到, 如果需要在renderjs访问逻辑层的话不要使用setup语法糖 (后续官方可能也会支持的)直接css隐藏
>>> .amap-logo,
>>> .amap-copyright {
display: none !important;
}
我是直接在组件样式层加的,不加深度选择器 样式不生效不知道为啥,写到外面可以不加 忙猜…算了不盲猜了
安卓端添加Marker时,或者自定义Marker设置图片时,图片会加载失败
下面这段代码在手机上就看不到默认的图标
new AMap.Marker({
position: new AMap.LngLat(116.39, 39.9), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: '北京'
})