一、背景

最近将一个小程序项目转化为 APP,想着正好体验一下 uniapp 宣称的一套代码,多端运行理念,于是运行到了真机环境。好消息是运行成功了,坏消息是部分样式不完善,部分功能失效。跨端成功了,但没完全成功。

二、问题描述

小程序项目页面都是用 vue 编写的,在某个页面中需要同时用到 map 和 canvas 组件,项目运行后 canvas 表现正常,但是 map 效果很一般。查询 uniapp 官方文档可知:App端使用 map 推荐使用 nvue,使用 canvas 推荐使用 vue。于是问题的关键就是让 map 用 nvue 编写,然后嵌入 vue 页面。经查询,uniapp 提供了 subNvue 可以解决我的问题。于是我就按照文档进行配置开发,运行后发现 map 上的 marker 不显示,控制台也没报错。 于是开启了 debug 之旅:先是打印了 mapContext,发现其不为 null。然后在 mapContext.addMarkers() 方法中添加 success() 回调和 fail() 回调,并在回调函数中打印日志,根据控制台打印结果来看,执行了 success() 回调,但是参数 res 却为空对象 {}。 在我印象中,如果 API 成功执行了, success() 回调的 res 参数会输出为 { errMsg: "ok" }。所以,mapContext.addMarkers() 在 subNvue 中的执行结果为:如成功。 一时间没有了头绪,便开启了 Search 之旅。2000 Years Later, 根据 uniapp官方提供的map组件使用问题 一文中提到:

问题4:map组件的相关JS API使用无效? 这种情况下,通过 uni.createMapContext() 获取到了地图对象,但是使用相关的 API 却无效。我们使用 map 的页面必须是在pages.json 配置,并且可以使用路由跳转的页面,否则就会导致相关的 JS API 使用无效,博主遇到此问题时,是在 subNvue 页面中使用了相关的 JS API。

发现博主和我遇到了一样的问题。通过评论交流后,博主推荐使用 nvue 页面实现相关地图功能。 于是乎,我尝试更换为 nvue 页面。这一次,map 表现正常,但是控制台直接报了 canvas 的错误。经过查询 canvas 组件文档 发现,可以使用 第三方 js 库,然后进行尝试后运行,又双叒叕发现了新问题,控制台报错:

reportJSException >>>> exception function:gcanvas setBackGround for android view, exception:WX_RENDER_ERR_TEXTURE_SETBACKGROUND: TextureView doesn't support displaying a background drawable!

再次 Search 发现有很多人都遇到了这个问题,甚至官方的人员都不太建议用这个库。 [1] [2] [3] 路再一次被封死了,我真是无语啦~ 没办法,只能继续查。中间实在有些破防了,便在官方社区发了个帖子,等待回复的过程中继续查。查啊查啊查,查啊查啊查,终于又查到一个 uniapp nvue map中刚踩到的坑 解决markers和polyline不显示,博主在文章中直言:uniapp 真是个神奇的框架,我看到后直接就笑了,很是赞同。根据文章中的办法,最后解决了我的问题,方法在下面👇。

三、解决方法

map 中绑定的 marker不能是在 data 中的,而是需要在计算属性中返回。

<map id="my-map" :markers="markers"></map>
export default {
	data() {
		return {
			map_markers: []
		}
	},
	computed: {
		markers() {
			return this.map_markers
		}
	},
	methods: {
		test() {
			// 1. 清除 marker
			this.map_markers = []
			
			// 2. 显示 marker
			this.map_markers = [{
				id: 1,
				iconPath: 'xxx',
				longitude: 120.1234,
				latitude: 30.5678,
				width: 12,
				height: 24
			}]

			// 注:this.mapContext.removeMarkers() 和 addMarkers() 调用后无效,markers 不会在 map 上显示
		}
	}
}

该方法虽然解决了subNvue页面中地图 marker 显示的问题,但是问题的根源应该是 uniapp 框架自身的 bug,

四、碎碎念

以前总在网上看到吐槽使用 uniapp 开发 APP 的评论和帖子,感觉不以为然。因为也用它做了几个小程序,虽说有槽点,但总体还能接受,毕竟开源不易。但是这次开发 APP 遇到这种问题,而且在开发其他功能时也不太顺利,感觉 uniapp 确实不太适合开发 APP,我算是被劝退了,下次再开发 APP 还是选择使用 React Native 或者 Flutter 更为良策。