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

相关推荐
木易 士心21 小时前
Vue 3 Props 响应式深度解析:从原理到最佳实践
前端·javascript·vue.js
海鸥两三1 天前
uniapp 小程序引入 uview plus 框架,获得精美的UI框架
前端·vue.js·ui·小程序·uni-app
lightgis1 天前
16openlayers加载COG(云优化Geotiff)
前端·javascript·html·html5
小飞大王6661 天前
TypeScript核心类型系统完全指南
前端·javascript·typescript
你的人类朋友1 天前
✍️记录自己的git分支管理实践
前端·git·后端
合作小小程序员小小店1 天前
web网页开发,在线考勤管理系统,基于Idea,html,css,vue,java,springboot,mysql
java·前端·vue.js·后端·intellij-idea·springboot
防火墙在线1 天前
前后端通信加解密(Web Crypto API )
前端·vue.js·网络协议·node.js·express
Jacky-0081 天前
Node + vite + React 创建项目
前端·react.js·前端框架
CoderYanger1 天前
前端基础——CSS练习项目:百度热榜实现
开发语言·前端·css·百度·html·1024程序员节
i_am_a_div_日积月累_1 天前
10个css更新
前端·css