uniapp+arcgis系列(三):邏輯層和視圖層RenderJS之間的相互通信



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>



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM