解析ArcGIS API for JavaScript全新开发模式
01
—
ArcGIS API for JavaScript的发展进程
ArcGIS API for JavaScript发展至今,已经更新迭代了好几个版本了。相信用过的小伙伴都知道,HTML4时代在页面上使用ArcGIS API for JavaScript还是用着古老的Dojo框架,很大原因是因为ArcGIS API for JavaScript基于Dojo开发因此也离不开Dojo。如今的前端开发早已是React、Vue、Angular三大框架的天下了,Dojo框架没有跟上新的ES6标准,适应不了现代JS的开发环境,使得国内几乎没有人在基于Dojo进行web开发,加上ArcGIS API for JavaScript在本机上部署安装十分麻烦,让很多行业内的前端开发者们觉得ArcGIS API for JavaScript十分的不友好。
后来,Esri官方发布了“esri-loader”,是将Dojo的AMD加载器进行封装并转换成了ES6标准的promise模式进行加载,让ArcGIS API for JavaScript能够很好的在ES6的环境下使用,而且“esri-loader ”是使用 TypeScript 开发,并以 npm 包的形式发布,我们只需要在项目中用npm安装esri-loader库,就可以从ArcGIS CDN托管API的构建中延迟加载模块,快速的在项目中安装部署ArcGIS API for JavaScript,这种方法通常被称为AMD模块构建。
AMD模块构建采用异步的方式加载模块,所以在使用“esri-loader”时想要加载ArcGIS API for JavaScript中的某一个API模块的话,需要通过方法esriLoader.loadModules,按照dojo中require引入模块的写法将模块加载进来,然后才能进行相应的功能开发。尽管在ES6环境下通过AMD模块构建的方法已经能够很好的使用ArcGIS API for JavaScript了,但这却不是一个方便、简洁的开发模式,AMD方法会预先加载所有的依赖,直到使用时候才执行,会浪费掉许多的资源,因此我们更希望的一种开发方式,是能够在代码的顶部引入模块,只执行一次就能够在代码中使用。
而ArcGIS API for JavaScript 4.18与4.19版本的发布彻底打破了这一尴尬的局面。在ArcGIS API for JavaScript4.18发布了ES modules的测试版,我们可以实现直接在组件顶部引入所需的API模块,然后在组件代码任何地方即可使用。紧接着4.19版本真正推出了正式版,一个振奋人心的消息!现在ArcGIS API for JavaScript能够支持ES modules了,这将意味着开发人员能够在不同的框架和工具上更好的使用它。
02
—
ArcGISAPI for JavaScript的ES modules
ES modules(ESM) 是JavaScript 官方的标准化模块系统,是用于处理模块的 ECMAScript标准,具有高分离、高复用的特点,很好的避免了引用模块时造成的命名冲突,而且现在所有主流的浏览器都能够支持ES modules。新的ArcGIS API for JavaScript的ES modules可以直接通过npm下载,只需短短一条命令:
npm install @arcgis/core
就可以将模块安装到你的项目中了
03
—
在React上使用ArcGIS API for JavaScript
接下来我将通过一个在React框架上的小例子,来展示ArcGIS API for JavaScript的ES modules。
首先用脚手架创建一个React的项目
接着安装ArcGIS API for JavaScript到我们在项目里,在终端输入命令:
npm install @arcgis/core
等待安装完成后,可以在node_modules目录中找到@arcgis/core文件,然后将assets文件复制到public目录中即可完成安装部署(也可以通过命令ncp完成)。
安装部署完成后,我们将开始实现我们的小例子了,目标是能够在页面上展示一个要素图层。
import React, {Component} from 'react';
import Map from "@arcgis/core/WebMap";
import MapView from "@arcgis/core/views/MapView";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer";
在render中写好一个div标签,设置好样式,这个标签将作为展示地图的容器。用ref属性给div标签设定好一个标识,标识为对象this.mapin。
render() {
return (
<div ref={this.mapin} style={{
padding: "0",
margin: "0",
height: "500px",
width: "100%"
}}
></div>
)
}
React的ref属性可以用来绑定render()输出的任何组件上,可以是一个字符串,也可以是一个回调函数或者是对象。因为我们创建好的地图需要一个容器来存放,所以我们需要通过CreateRef方法创建Refs并通过ref属性与容器进行联系,这样当ref属性绑定对象时,该对象下的current属性就指向了绑定的容器了。
我们在componentDidMount函数中定义好一个map实例来定义我们的底图,还有MapView用于呈现地图。在container中引用我们的DOM容器:
mapin = React.createRef()
componentDidMount() {=
const map = new Map({
basemap: "topo-vector",
})
const view = new MapView({
map: map,
container: this.mapin.current,
})
}
在App.js中将组件ArcgisAPI引入,运行项目。
可以看到基础地图已经展示到我们的页面上了
接着定义一个layer1为FeatureLayer实例,需要通过Portal发布好FeatureLayer图层,然后在实例中插入图层对应的url,最后用map.add方法添加layer1,运行我们的项目。
const layer1 = new FeatureLayer({
url:
"https://p15v.arcgisonline.cn/server/rest/services/Hosted/quhua/FeatureServer",
})
map.add(layer1);
我们的要素图层完美的加载到了我们网页上了。
完整代码:
import React, {Component} from 'react';
import Map from "@arcgis/core/WebMap";
import MapView from "@arcgis/core/views/MapView";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer";
export default class APP extends Component {
mapin = React.createRef()
componentDidMount() {
const map = new Map({
basemap: "topo-vector",
})
const view = new MapView({
map: map,
container: this.mapin.current,
})
const layer1 = new FeatureLayer({
url:
"https://www.arcgisonline.cn/server/rest/services/Hosted/quhua/FeatureServer",
})
map.add(layer1);//添加图层
}
render() {
return (
<div ref={this.mapin} style={{
padding: "0",
margin: "0",
height: "500px",
width: "100%"
}}
></div>
{/*设置容器*/}
)}
}
可以很明显的感觉出,相比于4.18前的 “esri-loader”方法,新的方法不但高效、简洁,并且更适应现在的模块化、组件化编程,是主流浏览器所采用的标准,更加方便前端开发人员的理解和使用。
当然,如果你是函数组件,在对ref使用上还可以更换为react官方更加推崇的Hooks用法。
/*Hook用法*/
import React, {useRef, useEffect} from 'react';
import Map from "@arcgis/core/WebMap";
import MapView from "@arcgis/core/views/MapView";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer";
function App() {
const mapin=useRef(null);
useEffect(() => {
const map=new Map({
basemap: "topo-vector",
})
const view=new MapView({
map: map,
container:mapin.current,
})
const layer1 = new FeatureLayer({
url:
"https://p15v.arcgisonline.cn/server/rest/services/Hosted/quhua/FeatureServer",
})
map.add(layer1);
},[])
return <div ref={mapin} style={{
padding: "0",
margin: "0",
height: "500px",
width: "100%"}}
></div>
}
export default App;
2021年易智瑞空间信息技术开发者大会
6月3-4日
北京 中国职工之家
识别下方二维码,报名参会