ArcGIS JSAPI 源码解读 之 Accessor元数据

ArcGIS作为一个出色的商业化体系软件,其横跨了多种不同的技术架构和编程语言,而其优秀之处就在于多种不同的产品和SDK之间实现了良好的兼容性。

Accessor作为整套SDK的底层数据结构,包括Webmap、WebScene、各种Renderers、各种Symbols都通过继承Accessor而来。为了让ArcGIS Maps SDK for JavaScript中的多种不同类型的数据与ArcGIS Pro桌面端、Enterprise Apps乃至移动端之间实现良好的交换,Esri通过基于JSON的通用可交换格式设计来提供技术上的支持。

正是因为这些软件体系层面的考虑,JavaScript SDK可能在运行时通过网络加载来自外部的JSON格式数据,并动态的将这些JSON数据转换为SDK内部基于Accessor的对象,从而满足SDK内部运行的需要。Esri官方将这个过程称之为"AutoCast",而基于JSON的对象描述首先会在Accessor内部进行解析,并生成更丰富和规范的内部数据结构,这是作为Accessor的元数据进行存储的。

在Accessor实现中,通过createSubclass继承并构建子类型时即生成了该类型的元数据。

JavaScript 复制代码
class Accessor {
	static createSubclass(args) {
		// 此处省略...
		const AccessorType = this;
		class o extends AccessorType {
			// 此处省略...
		}
		getPropertiesMetadata(o.prototype);
	}
}

getPropertiesMetadata为动态生成的新类型附加元数据存储对象__accessorMetadata__,这里由于逐级继承的缘故,函数检查了__accessorMetadata__是否直接位于当前类型下,避免父类型造成的干扰。同时,为保持与JavaScript语言原型链逻辑的一致性,对于多级继承的类型,同步克隆了上一级类型下的所有元数据属性。

JavaScript 复制代码
function getPropertiesMetadata(proto) {
	// 获取类构造器原型链上的__accessorMetadata__
	let metaStore = proto.constructor.__accessorMetadata__;

	// 判断该__accessorMetadata__对象是否定义在当前类型,false则表示来自父类的定义
	const isMyStore = Object.prototype.hasOwnProperty.call(
		proto.constructor,
		'__accessorMetadata__'
	);

	if (metaStore) {
		if (!isMyStore) {
			metaStore = Object.create(metaStore);
			for (const p in metaStore) {
				metaStore[p] = lang.clone(metaStore[p])
			}
			Object.defineProperty(proto.constructor, '__accessorMetadata__', {
				value: metaStore,
				enumerable: !1,  
				configurable: !0,  
				writable: !0,
			});
		}
	} else {
		metaStore = {}
		Object.defineProperty(proto.constructor, '__accessorMetadata__', {
			value: metaStore,
			enumerable: !1,  
			configurable: !0,  
			writable: !0,
		});
	}
	return proto.constructor.__accessorMetadata__;
}

至此,子类型完成了自身的类型创建并从父类型中继承了已有的属性元数据,下一步将是逐个解析类型构建中传递的properties属性,并构造属于该类型自身的属性元数据。

JavaScript 复制代码
class Accessor {
	static createSubclass(args) {
		// 此处省略...
		const AccessorType = this;
		class o extends AccessorType {
			// 此处省略...
		}

		// 第一步准备元数据对象
		getPropertiesMetadata(o.prototype);

		// 逐个解析传入的其他属性元信息
		// 此处省略


		// 遍历properties对象中的属性声明,并补充到__accessorMetadata__
		for (const p in properties) {
			const typeDesc = predicateType(properties[p])
			property(typeDesc)(o.prototype, p);
		}
	}
}

稍后让我们再详细了解property装饰器是如何对单个的属性进行建模和存储的。

如果你觉得本文对你有些许启发,请持续关注我的公众号"戈伊星球"吧!

相关推荐
0和1的舞者4 小时前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
web小白成长日记5 小时前
在Vue样式中使用JavaScript 变量(CSS 变量注入)
前端·javascript·css·vue.js
QT 小鲜肉5 小时前
【Linux命令大全】001.文件管理之which命令(实操篇)
linux·运维·服务器·前端·chrome·笔记
C_心欲无痕5 小时前
react - useImperativeHandle让子组件“暴露方法”给父组件调用
前端·javascript·react.js
BullSmall7 小时前
支持离线配置修改及删除操作的实现方案
前端
全栈前端老曹7 小时前
【前端路由】Vue Router 嵌套路由 - 配置父子级路由、命名视图、动态路径匹配
前端·javascript·vue.js·node.js·ecmascript·vue-router·前端路由
EndingCoder7 小时前
安装和设置 TypeScript 开发环境
前端·javascript·typescript
张雨zy8 小时前
Vue 项目管理数据时,Cookie、Pinia 和 LocalStorage 三种常见的工具的选择
前端·javascript·vue.js
五月君_8 小时前
Nuxt UI v4.3 发布:原生 AI 富文本编辑器来了,Vue 生态又添一员猛将!
前端·javascript·vue.js·人工智能·ui
!执行8 小时前
遇到 Git 提示大文件无法上传确实让人头疼
前端·github