github地址:點擊此處跳轉
uniapp-arcgis系列目錄:
uniapp+arcgis系列(一): uniapp引入ArcGis for JS 4.x,並加載地圖服務、顯示地圖,去除邊框、水印和縮放按鈕
uniapp+arcgis系列(二): 在外部調用arcgis api,地圖加載完成事件
uniapp+arcgis系列(三):邏輯層和視圖層RenderJS之間的相互通信
uniapp+arcgis系列(四): 獲取wgs84坐標、獲取火星坐標GCJ-02以及當前位置信息的省市街道地址名稱、poi興趣點,點擊地圖畫點和軌跡
由於地圖是加載在視圖層的,所以掌握視圖層和邏輯層雙向通信的方法是必須的。
一、視圖層RenderJS主動和邏輯層通信
這里相對簡單,需要在renderJS中調邏輯層的方法,通過特定的方式直接調就行了。
首先在邏輯層中定義一個給視圖層調用的方法:
<!-- 邏輯層代碼 -->
<script>
export default {
data() {
return {}
},
methods: {
/**
* 給renderJS調用的方法
*/
methodForRenderJs:function(val){
console.log("我是邏輯層,被視圖層調用了,並且收到參數:");
console.log(val);
},
}
}
</script>
然后在業務層調用這個方法:
this.$ownerInstance.callMethod('methodForRenderJs',{val1:"參數1",val2:"參數2"});
控制台輸出:
二、邏輯層主動和視圖層RenderJS通信
實話實說這個有點抽象。
因為邏輯層是不能直接主動通信視圖層,只能向視圖層添加一個屬性,並且在視圖層為這個屬性綁定一個變化事件,邏輯層通過對這個屬性值動手動腳,來達到向視圖層傳遞數據、調用視圖層的方法的效果。
所以划重點:邏輯層離了view是沒辦法和視圖層通信的!!!離開了這個頁面view作廢!!!通信作廢!!!
如果離開當前頁面以后,仍然需要arcgis在后台一直持續不停地處理數據,用這種方法是行不通的!!!放棄arcgis罷。
簡單概括下:
在視圖層的view,給view綁定一個屬性msg,再綁定一個msg的變化事件。
像這樣:
<view :msg="valueChangeSign" :change:msg="myMapViews.valueChange" type="default"></view>
- valueChangeSign 是定義在邏輯層中的data{return{}}里面的屬性
- myMapViews是邏輯層的module
<script module="myMapViews" lang="renderjs">
- valueChange 是定義在視圖層的method里面的方法
valueChange(newVal, oldVal, ownerVm, vm) {
console.log("我是新數據....");
console.log(newVal);
console.log("我是舊數據....");
console.log(oldVal);
},
valueChangeSign的值改變,會觸發valueChange這個事件,並且該事件可以拿到新的值、舊的值。
可以通過在邏輯層中操作valueChangeSign來觸發這個事件並且傳遞數據。
如果只是想單純的觸發事件,可以將valueChangeSign的值設置為系統當前時間的毫秒數,確保它一定會變化。
this.valueChangeSign = new Date().getTime();
如果不僅需要觸發事件,還需要傳遞一個復雜的對象作為參數,就是達到vue中的深度監聽的效果,可以寫成這樣:
var map = new Map();
map["name"] = "邏輯層";
map["value"] = "傳遞值";
this.valueChangeSign = [new Date().getTime(), map];
valueChange(newVal, oldVal, ownerVm, vm) {
var map = newVal[1];
},
傳遞一個數組,把數組的0設置為系統時間毫秒數,這樣既可以傳遞復雜對象,也能保證事件觸發。
控制台輸出:
來看一下效果:
這里我是添加了一個定時器來改變值。
三、完整代碼
<template>
<view>
<view :msg="valueChangeSign" :change:msg="myMapViews.valueChange" type="default"></view>
<template>
<view style="width: 350px;height: 600px;" id="myMapView" />
</template>
</view>
</template>
<!-- 邏輯層代碼 -->
<script>
export default {
data() {
return {
valueChangeSign:"", // 調用視圖層方法的信號
}
},
methods: {
/**
* 給renderJS調用的方法
*/
methodForRenderJs:function(val){
console.log("我是邏輯層,被視圖層調用了,並且收到參數:");
console.log(val);
},
},
onShow() {
let this_ = this;
setInterval(function(){
var map = new Map();
map["name"] = "邏輯層";
map["value"] = "傳遞值";
this_.valueChangeSign = [new Date().getTime(),map];
},5000);
}
}
</script>
<!-- RenderJS視圖層代碼 -->
<script module="myMapViews" lang="renderjs">
import {
loadModules
} from 'esri-loader'
export default {
name: 'myMapView',
data() {
return {
myMapObject: {}, // 對象,存儲關於地圖的圖層、方法、屬性等
}
},
methods: {
createMapView() {
var this_ = this;
return new Promise(function(resolve){
const options = {
url: 'https://js.arcgis.com/4.14/init.js',
css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'
};
loadModules([
"esri/Map",
"esri/views/MapView",
"esri/Basemap",
"esri/layers/Layer",
"esri/layers/TileLayer",
], options).then(([Map, MapView, Basemap, Layer, TileLayer]) => {
// 地圖的底圖
var url =
"http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineCommunity_Mobile/MapServer";
var basemaplayer = new TileLayer({
url: url,
visible: true,
});
// 地圖對象
var map = new Map({
basemap: "", // 底圖置空
layers: [basemaplayer], // 添加自定義的layer為底圖
});
// 創建一個mapView並綁定頁面元素
var view = new MapView({
container: "myMapView",
map: map,
zoom: 1, // 縮放比例 值越大圖越大
});
// 地圖加載完成事件
view.when(function() {
console.log("地圖加載完成了!");
resolve();
});
// 定義myMapObject的方法供外部調用
this_.myMapObject.methodForOutSide = function(val){
console.log("methodForOutSide方法被調用了:"+val);
}
this_.myMapObject.map = map;
})
})
},
valueChange(newVal, oldVal, ownerVm, vm) {
console.log("我是視圖層,我被邏輯層調用了...");
console.log("我是新數據....");
console.log(newVal);
console.log("我是舊數據....");
console.log(oldVal);
var map = newVal[1];
},
},
mounted() {
// 頁面初始化完成后
var this_ = this;
this.createMapView().then(function(){
console.log("加載地圖的promise執行結束了....")
// 打印地圖對象
console.log(this_.myMapObject.map);
// 調用createMapView()內部的方法
this_.myMapObject.methodForOutSide();
// renderJs主動調用邏輯層的方法
this_.$ownerInstance.callMethod('methodForRenderJs',{val1:"參數1",val2:"參數2"});
});
},
}
</script>
<style>
/deep/.esri-widget--button {
display: none;
}
/deep/.esri-attribution__powered-by {
display: none;
}
/deep/.esri-view .esri-view-surface--inset-outline:focus::after {
outline: none;
}
</style>