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

相关推荐
炫饭第一名1 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫2 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊2 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter2 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折2 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_2 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
不会敲代码12 小时前
前端组件化样式隔离实战:React CSS Modules、styled-components 与 Vue scoped 对比
css·vue.js·react.js
Angelial2 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu3 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu3 小时前
Angular6学习笔记13:HTTP(3)
前端