Skip to content

MeshHelloWorld

Zhexuan Liu edited this page Jun 21, 2018 · 7 revisions

开发一个简单的 Mesh Package

本文档首先介绍了 Mesh Package 中的基本概念,然后通过一个简单的 package 范例介绍了如何开发一个可以让飞机起飞、返航的 package

Mesh Package 的基本概念

该章节中我们会介绍 package 中的基本概念,以及对应的对象、属性。这里介绍的概念会在后面的两个范例中使用到,请务必先弄明白,如果有疑问和疑惑,可以联系奇志信息科技有限公司。

页面组件

页面组件的思想与 React 的思想完全一致。不同之处在于,envoy 中的页面组件是轻量的、为 MeshPackages 开发定制的,这些定制组件由 mesh-envoy-tag 暴露。开发者也可以在这些暴露好的组件的基础上根据自身需求进行自定义的组装和开发。

简而言之,页面的组件将 package 中的每个页面拆分成不同的组件,并允许绑定相关属性和事件,使用 jsx 语法进行编写。最后将编写好的组件传给 envoy 进行渲染。

定制的页面组件的具体信息、属性、事件请参照 页面组件文档

envoy

envoy 是 JS 引擎的核心,负责与原生通信以及渲染逻辑。渲染的方法十分简单,如下范例:

import envoy, { linkEvent } from 'mesh-envoy'
import Component from 'mesh-envoy-component'
import { Provider, connect } from 'mesh-envoy-mobx'
import { PlainLabel, MainPage } from 'mesh-envoy-tag'
import store from './store'

class App extends Component
{
	constructor(props)
	{
		super(props);
	}

	render()
	{
		return (
			<MainPage>
				<PlainLabel>Hello World</PlainLabel>
			</MainPage>
		)
	}
}

envoy.render(
	<Provider myStore={ store }>
		<App />
	</Provider>
)

该实例是一个完整的组件定义和渲染的过程,渲染的是一个含有 Hello World 标签的 package 主页。具体的细节会在后面具体的开发教程中进行阐述,这里想向读者暂时的是调用 envoy.render 方法进行渲染,传入该方法的需要是一个 envoy 中支持的页面组件

featureManager

featureManager 是 mesh-envoy 暴露出来的一个基类,主要是用于封装使用 featureControl 在协作中获取飞机信息、执行任务、操控飞机的操作。基类中已经基本封装好了必要的接口,详情可以查看 featureManager 的文档。下图勾勒了 featureManager 在 package 中进行一次协作的基本流程。

image

上图表示的是在两台设备 DeviceA 和 DeviceB 上,假如 DeviceB 直连着飞机,而 DeviceA 想访问 DeviceB 连接的飞机的位置时,在 package 层面事件和数据的流动过程。

开发 package 时,请声明一个 featureManager 类继承 mesh-envoy 暴露出来的基类,并调用基类的 constructor。如果开发者需要监听自定义事件,可以 featureManager 类中定义 registerHandler 方法,并在方法内进行定义

以下为 package 中的 featureManager 的范例:

import { event, FeatureManager } from 'mesh-envoy'

class MyFeatureManager extends FeatureManager
{
	constructor()
	{
		super();
	}

	registHandler()
	{
		mesh.log('regist event handler')
		event.on('homepoint', async () =>
		{
			if (mesh.aircraft)
			{
				return await this.getHomepoint(mesh.aircraft.deviceID)
			}
		})
		event.on('location', async () =>
		{
			if (mesh.aircraft)
			{
				return await this.getCurrentLocation(mesh.aircraft.deviceID);
			}
		})
	}
}

export default new MyFeatureManager()

上面的示例中,我们自定义了两个事件 homepointlocation ,并对它们进行了监听。一旦相关事件触发了,就会调用定义好的回调来获取相关信息。

更多 featureManager 基类相关的信息请关注 featureManager 文档。

store

Store 是 mesh-envoy-mobx 暴露出来的一个组件,其原理与 mobx 一致。在 package 开发中,store 的作用主要是用来储存和传递必要的任务和 feature 相关的设置以及数据,以及将这些数据和不同的设备对应上。

一个典型的 store 的声明 (store.js) 如以下范例

import { observable, action } from 'mesh-envoy-mobx'

class Store
{
	@observable foo = 'bar';

	/**
	 * Map between device and featureData for ReturnHome feature
	 */
	returnHomeDeviceFeatureDataMap = {};

	/**
	 * Action to set rackToHomeDeviceFeatureDataMap
	 */
	@action setReturnHomeDeviceFeatureDataMap = (map) =>
	{
		this.returnHomeDeviceFeatureDataMap = Object.assign({}, this.returnHomeDeviceFeatureDataMap, map);
	}
}

const store = new Store()

export default store

上面示例中定义的 store 中储存了一个对应设备以及 returnHome feature 的数据的 map,以及暴露了设置它的方法。在后续 package 开发中,只需如此引用和调用 store 即可:

import store from './store'

store.setReturnHomeDeviceFeatureDataMap({});

一般来说,store 都会作为一个全局的对象在页面中通过 props 进行传递,所以在后续的示例中你会看到类似这样的调用

instance.props.myStore.setReturnHomeDeviceFeatureDataMap({});

其中 instance 是当前页面的上下文。

开发一个简单的 HelloWorld package

该章节中的所有代码都可在 HelloWorld 中找到

在阅读完 简介 文档后现在你的项目中已经有了下列文件

	├── envoy.config.js 						// envoy config 文件
	├── node_modules/							// 安装的依赖将被放置在这个目录下
	├── package.json							// 依赖和配置的定义
	├── src/									// 所有开发代码都放在该目录下
	├── yarn.lock 								// 依赖控制
	├── eslintrc								// (可选) 定义 eslint 的语法检查规则
	├── .babelrc								// babel 的配置文件

下面我们将在 src 文件夹中添加代码完成一个简单的 HelloWorld package 的开发。

创建 resource 文件夹

在项目的根目录下创建 resource 文件夹,并在文件夹里添加 .gitkeep 文件已确保该文件夹被同步到 git 上。

这个文件夹以后会用来存放 feature 的图标等静态文件,现在先创建一个空的文件夹是为了通过编译和打包的过程。执行完这一步后你的项目目录应该是

	├── envoy.config.js 						// envoy config 文件
	├── node_modules/							// 安装的依赖将被放置在这个目录下
	├── package.json							// 依赖和配置的定义
	├── resource/								// 新建的 resource 文件夹
			├── .gitkep
	├── src/									// 所有开发代码都放在该目录下
	├── yarn.lock 								// 依赖控制
	├── eslintrc								// (可选) 定义 eslint 的语法检查规则
	├── .babelrc								// babel 的配置文件

首先先创建 index.js 文件

该文件将作为 package 的主入口,创建完后项目的目录应该是

	├── envoy.config.js 						// envoy config 文件
	├── node_modules/							// 安装的依赖将被放置在这个目录下
	├── package.json							// 依赖和配置的定义
	├── resource/								// 新建的 resource 文件夹
			├── .gitkep
	├── src/									// 所有开发代码都放在该目录下
			├── index.js
	├── yarn.lock 								// 依赖控制
	├── eslintrc								// (可选) 定义 eslint 的语法检查规则
	├── .babelrc								// babel 的配置文件

在 index.js 中添加如下代码

import envoy from 'mesh-envoy'
import Component from 'mesh-envoy-component'
import { MainPage, FeatureList } from 'mesh-envoy-tag'

class App extends Component
{
	constructor(props)
	{
		super(props);
	}

	render()
	{
		return (
			<MainPage>
				<FeatureList>
					<FeatureList.Feature
						id="test"
					>
						Hello World
					</FeatureList.Feature>
				</FeatureList>
			</MainPage>
		)
	}
}

envoy.render(
	<App />
)

这里我们声明了一个新的页面组件叫做 App,该页面组件必须继承自 mesh-envoy-component 暴露出来的 Component 基类,且在 constructor 中调用基类的 constructor。除此之外,该页面组件类中必须含有 render 方法,且该方法必须返回一个组件。

然后我们将这个 App 页面组件类用 JSX 语法传入 envoy.render 方法中,完成页面的渲染

以上就是这个简单的 package 的所有代码

本地环境编译

编译前请确保本地的 3000 端口没有被占用,因为编译的脚本会使用到该端口。

在项目环境的根目录中执行以下命令

yarn dev

在命令行中没有报错的话,可以看到项目中增加了一个 dist 文件夹和一个 zip 文件夹。这两个文件夹就是编译好的 package 代码以及打包好的文件。该命令还会在本地开启一个小型服务器,自动将打包好的 zip 文件放在本地的 3000 端口上。

此时可以在 Mesh App 中选择加载你本机 serve 的 package (通过本机的 ip 和 3000 端口来定位)

最终效果

在 Mesh App 中读取了本地的 package 后能看到的最终效果为

image

What's Next

接下来可以阅读 MeshFirstTakeOff 文档 来学习更复杂的 package 开发,该教程将指导你实现让飞机起飞、返航等操作。

Clone this wiki locally