1.前言
在开发cesium项目的时候,我们都需要开发一些小组件,如实时展示地图经纬度组件、图层管理器、绘制工具等等,如果把他们都放在一个cesium组件中,代码会变得非常庞大,因此我们需要将它们独立起来,但是问题在于viewer怎么访问呢?可否共享?本次教大家怎么开发cesium 的组件。
温馨提示:
在vue中使用注意不要把cesium的任何实例变成响应式(如vue2放在data里),数据的监听和响应会严重影响性能。变量可申明在export外面。如下图tileLayer就是一个primative的json,key为id,value为primative实例,这种方法还可以方便查询,直接tileLayer【id】即可
2.多组件使用viewer
①全局挂载(最佳)
涉及到多组件的使用,最方便的方法是window.viewer = viewer,但是注意创建viewer的组件应该作为子组件,否则获取不到window.viewer。如下图所示,我是在Cesium组件挂载的viewer,同级的FooterTools、ToolLatLonVue就可以通过window.viewer获取,更高一级的组件也可。
Cesium组件:
window.viewer = viewer
父组件:
<template>
<div class="center">
<Cesium ref="cesium" :showToolBox="false" />
<div class="leftDrawer">
<div ref="leftDrawerContent" class="content">
<uavList/>
</div>
<span ref="leftDrawerBtn" class="btnShow" @click="showLeftDrawerContent"><i :class="{'el-icon-arrow-left':show3,'el-icon-arrow-right':!show3}"></i></span>
</div>
<FooterTools v-on:useCesiumFuc="useCesiumFuc"/>
<div style="position:absolute;right:0px;bottom:72px;width:auto;height:auto;z-index: 99;">
<ToolLatLonVue />
</div>
</div>
</template>
②props传递viewer
这种方法适用于父组件为地图组件,子组件为使用viewer的组件,相比上一种方法,麻烦在于每次定义子组件都要写一遍props,然后在watch里监听viewer是否传过来了,因为子组件会先渲染,然后再到父组件,当监听到了父组件viewer的变化(即赋值了),这时子组件再访问viewer就能正常使用了。案例如下:
子组件ToolsList:
watch: {
'viewer': function (val) {
if (val !== null) {
this.init()
}
},
},
props:['viewer'],
父组件:
<ToolsList :viewer="viewer"/>
③间接使用
1.子传父:this.$emit
父组件为地图,子通过this.$emit调用父组件的方法。
2.全局事件总线
该方法,没有层级限制,任何组件都可以用。
地图组件绑定:
// mounted里绑定
mounted(){
this.$bus.$on('clearEntityAll',(data)=>{
console.log('接收到清空所有图形',data)
this.clearEntityAll() //清空当前所有图层
})
}
// beforeDestroy解绑,一定要做!不然组件注销了还有这个方法,会莫名其妙调用
beforeDestroy() {
this.$bus.$off([
'clearEntityAll',
])
}
其他组件对地图组件访问:
this.$bus.$emit('clearEntityAll',this.data) // 传参
3. 总结
本人参与开发了一个cesium的大项目,也是从vue2半知半解上手的cesium,作为过来人经验,个人建议在实际开发中,优先考虑第一和第二种方法,因为间接访问方式,在涉及到很多地图操作时,地图组件会变得非常臃肿,data里面参数很多,methods也很多,后期维护和增加东西很麻烦,最好的方式还是把对viewer的相关操作写进自己各个功能对应的组件里,这样便于后期管理,debug也没那么复杂,尤其是全局事件总线不要随便用。