Vue 3 结合 ArcGIS Maps SDK for JavaScript 开发时,Pinia 中存放 MapView 或 Map 对象时报错

预期实现效果:

项目通过 Vue 3 + TypeScript + Pinia + ArcGIS Maps SDK for JavaScript 技术栈搭建,预期是想在初始化 MapView 过后将其存放在 Pinia 中作为一个全局状态来维护,便于其他组件使用。

报错文案:

Uncaught (in promise) TypeError: 'get' on proxy: property 'accessor' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#g4' but got '#g4')

报错截图:

代码组织结构:

pinia 初始化 store 文件:

js 复制代码
import { ref } from 'vue'  
import { defineStore } from 'pinia'  
  
export const useMapViewStore = defineStore('mapView', () => {  
  const mapView = ref({})  
  function setMapView(val: any) {  
    mapView.value = val  
  }  
  
  return { mapView, setMapView }  
})

初始化 MapView 文件:

js 复制代码
import { onMounted } from 'vue'  
import { useMapViewStore } from '@/stores/counter'  
import Map from '@arcgis/core/Map.js'  
import MapView from '@arcgis/core/views/MapView.js'  
import Basemap from '@arcgis/core/Basemap.js'  
// ......  
  
const mapViewStore = useMapViewStore()  
  
const initMap = () => {  
  const basemap = new Basemap({  
    baseLayers: [ /*初始化的底图图层*/ ]  
  })  
  
  const map = new Map({  
    basemap  
  })  
  
  const view = new MapView({  
    map,  
    container: 'map'  
  })  
  mapViewStore.setMapView(view)  
  
  // 其他业务逻辑代码 ......  
}  
  
onMounted(() => {  
  initMap()  
})

使用 store 中 mapView 的文件:

js 复制代码
import { useMapViewStore } from '@/stores/counter'  
// ......  
  
const mapViewStore = useMapViewStore()  
  
// 其他业务逻辑代码 ......  
  
const handleAddLayerToMap = () => {  
  const layerRes = new FeatureLayer({  
    url: layer.url,  
    id: layer.id  
  })  
  mapViewStore.mapView.map.add(layerRes)  
}  
  
// 其他业务逻辑代码 ......

解决方案:

通过打断点调试发现,代码最终走到 store 中的 setMapView() 方法时传入的参数还是正确的 view 值,但是在该方法中通过 mapView.value = val 这行代码将其赋值到 pinia 中的 mapView 时发生了错误,原因是 vue 3 中对于数据的监听机制导致的。

既然找到了原因,那解决方法不难,在 setMapView() 方法中对其赋值之前将传入的 view 值通过 markRaw() 方法转为普通对象即可,如下:

js 复制代码
import { ref, markRaw } from 'vue'  
// ......  
  
export const useMapViewStore = defineStore('mapView', () => {  
  const mapView = ref({})  
  function setMapView(val: any) {  
    mapView.value = markRaw(val)  
  }  
  
  return { mapView, setMapView }  
})

通过上述修改,浏览器控制台不再报错,在其他组件中通过 mapViewStore.mapView 也可以获取到存放在 pinia 中的 mapView 值。

相关推荐
Yao80618 分钟前
MinIO自建对象存储,省OSS费用的完整方案
前端·后端
2501_9339232526 分钟前
设计网页的时候加载不出来怎么办?认识常见的状态码
前端·spring
only-lucky33 分钟前
QML深入学习五(Controls模块)
前端·javascript·学习
程序员黑豆42 分钟前
鸿蒙应用开发之路由:Router 页面路由使用教程
前端·harmonyos
gyx_这个杀手不太冷静1 小时前
Agent开发进阶指南(第 2 章):Agent 运行全流程拆解、上下文窗口、流式输出、记忆系统与 Function Call 实战
前端·架构·agent
anyup1 小时前
像这种问题千万别自己动手,否则你可太看不起 AI 了
前端·架构·trae
hunterandroid2 小时前
[鸿蒙从零到一] HarmonyOS Web 组件与 JSBridge 通信实战:从页面加载到安全协议
前端
xingren2 小时前
「拍摄器」UI 特效 - 在 Winform/WPF/WinUI3/Avalonia/Web 的实现
前端
leslie1182 小时前
npm常用命令
前端·npm
艾伦野鸽ggg2 小时前
axios 基本操作
前端