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 值。

相关推荐
星夜夏空9912 分钟前
FreeRTOS学习(7)——任务列表
java·前端·学习
weixin_4713830340 分钟前
由浅入深递归练习
前端·javascript·vue.js
tedcloud1231 小时前
ai-engineering-from-scratch部署教程:从零搭建AI应用环境
服务器·前端·人工智能·系统架构·edge
Kurisu5751 小时前
全面战争:战锤3修改器下载2026最新
前端
丷丩1 小时前
MapLibre GL JS第21课:绘制GeoJSON点图标、注记
前端·javascript·gis·mapbox·maplibre gl js
LCG元1 小时前
现代Web应用高可用架构设计与性能调优实战
前端·wpf
丷丩2 小时前
MapLibre GL JS第20课:更新GeoJSON多边形
前端·javascript·gis·mapbox·maplibre gl js
swipe2 小时前
DeepAgents middleware 工程实战:把复杂 Agent 的运行时基建交给可组合中间件
前端·面试·llm
前端环境观察室2 小时前
别让 Agent 浏览器任务无限重试:失败分类、RetryPolicy 与人工复核
前端
喵个咪2 小时前
Headless 后端实践:基于Go的企业级多栈管理系统脚手架
前端·vue.js·react.js