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

相关推荐
LuciferHuang7 小时前
震惊!三万star开源项目竟有致命Bug?
前端·javascript·debug
GISer_Jing7 小时前
前端实习总结——案例与大纲
前端·javascript
天天进步20157 小时前
前端工程化:Webpack从入门到精通
前端·webpack·node.js
姑苏洛言8 小时前
编写产品需求文档:黄历日历小程序
前端·javascript·后端
知识分享小能手8 小时前
Vue3 学习教程,从入门到精通,使用 VSCode 开发 Vue3 的详细指南(3)
前端·javascript·vue.js·学习·前端框架·vue·vue3
姑苏洛言8 小时前
搭建一款结合传统黄历功能的日历小程序
前端·javascript·后端
你的人类朋友10 小时前
🤔什么时候用BFF架构?
前端·javascript·后端
知识分享小能手10 小时前
Bootstrap 5学习教程,从入门到精通,Bootstrap 5 表单验证语法知识点及案例代码(34)
前端·javascript·学习·typescript·bootstrap·html·css3
一只小灿灿10 小时前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉