
# 新建并开发自定义组件
#### 操作场景
当系统预置的组件无法满足用户需求时，用户可自定义组件包进行上传，在页面中进行使用。在开发自定义组件前，请仔细阅读[自定义组件开发规范](https://support.huaweicloud.com/usermanual-astrocanvas/astrocanvas_05_7116.html)章节内容，了解组件的开发规范。下面以开发网站中常用的柱状图（vue2+Echarts）组件为例，向您介绍如何开发自定义组件。
本节使用的示例组件开发过程中使用了前端开发框架[Vue](https://cn.vuejs.org/)及[Echarts](https://echarts.apache.org/zh/index.html)，请提前了解。
图1最终呈现效果   
![](https://support.huaweicloud.com/usermanual-astrocanvas/zh-cn_image_0000002158307769.png "点击放大")
#### 开发自定义组件
1. 下载图表模板。 
   1. 参考[登录华为云Astro大屏应用界面](https://support.huaweicloud.com/usermanual-astrocanvas/astrocanvas_05_6008.html)中操作，登录华为云Astro大屏应用界面。
   
   2. 单击页面右上角的"管理"，进入华为云Astro大屏应用管理页面。
   
   3. 在左侧导航栏中，选择"页面资产管理 \> 组件模板"。
      表1组件模板列表 
      | 组件模板名称                  | 功能                                                                                                                                                                                                                                                                                 |
      |:---|:---|
      | EchartsWidgetTemplate   | 基于Echarts实现的一个柱状图组件模板，包含基本配置项、单击系列的事件交互、数据对接等能力。                                                                                                                                                                                                                                   |
      | SelectWidgetTemplate    | 基于elmentUI和Vue2实现一个通用的下拉框组件模板，包含基本配置项、交互、数据对接等能力。                                                                                                                                                                                                                                  |
      | widgetVueTemplate       | 当需要使用Vue library时，请选用该模板。                                                                                                                                                                                                                                                          |
      | widgetPropertyTemplate  | 当需要自定义组件的一些属性时，请选用该模板。自定义属性会显示在组件的属性配置界面。                                                                                                                                                                                                                                          |
      | widgetActionTemplate    | 当自定义组件需要添加动作属性时，请选用该模板。 事件和动作都是Widget的配置属性，用于实现Widget之间的交互。例如，单击某个Widget内的按钮，另外一个Widget需要进行数据更新操作，或者是需要跳转到同个应用下的其他页面，这时需要通过事件和动作的机制来实现。单击按钮是触发一个事件，该Widget需要选用"widgetEventTemplate"模板，数据更新操作或者页面跳转操作是一个动作，该Widget需要选用"widgetActionTemplate"模板。 |
      | widgetEventTemplate     | 当自定义组件需要添加事件属性时，请选用该模板。                                                                                                                                                                                                                                                            |
      | widgetBridgeTemplate    | 当自定义组件需要通过桥接器调用后台数据时，请选用该模板。                                                                                                                                                                                                                                                       |
      | widgetPageMacroTemplate | 当需要使用页面宏来存储变量时，请选用该模板。                                                                                                                                                                                                                                                             |
         
      
   
   4. 在组件模板列表中，单击"EchartsWidgetTemplate"，进入模板详情页。
      图2选择EchartsWidgetTemplate模板   
      ![](https://support.huaweicloud.com/usermanual-astrocanvas/zh-cn_image_0000002123028020.png "点击放大") 
   
   5. 单击"下载"，将EchartsWidgetTemplate组件模板包下载到本地。
   
   6. 解压已下载的组件模板包，认识组件结构。
      表2组件文件结构 
      | 文件名                             | 文件说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
      |:---|:---|
      | EchartsWidgetTemplate.js        | 组件逻辑文件，整个Widget的渲染核心JS，在组件编辑状态和页面最终的发布运行态都会被加载执行。主要包含的预置API说明请参见[表3]。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
      | EchartsWidgetTemplate.editor.js | 组件属性定义文件，负责组件在编辑状态时需要渲染的界面和逻辑。"\*.editor.js"只在组件编辑状态被加载，主要包含： - propertiesConfig方法：主要负责组件配置页面中右侧的属性配置逻辑。  - create方法：仅在组件首次被创建时调用一次。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
      | EchartsWidgetTemplate.css       | 组件的样式文件，在该文件中编写组件的CSS样式。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
      | EchartsWidgetTemplate.ftl       | 组件DOM结构文件，需要在服务端提前渲染的部分可以写在此文件中，相当于HTML文件，负责样式展示。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
      | packageinfo.json                | 组件的元数据描述文件。 - widgetApi name：组件的名称。  - widgetDescription：组件的描述信息。  - authorName: ：组件的作者信息。  - localFileBasePath：组件本地调测路径。  - i18n：指定组件的国际化资源文件（本例模板中未体现）。  - requires：依赖的库名称和版本号。  - width：在绝对布局高级页面中，添加该组件时的默认宽度，单位为px，不填写默认为200px（本例模板中未体现）。  - height：在绝对布局高级页面中，添加该组件时的默认高度，单位为px，不填写默认为200px（本例模板中未体现）。   |
      | messages-zh/messages-en.json    | 组件的国际化资源文件，用于配置多语言（本例模板中未体现）。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
         
       表3*组件名* .js中预置API说明 
      | 分类                | API及说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
      |:---|:---|
      | 组件实例预置API         | - init方法：主要包含组件渲染需要初始化数据的入口函数。  - render方法：负责整个组件渲染的业务逻辑方法。  - getConnectorProperties：获取桥接器属性的配置值。  - getConnectorInstanceByName：通过桥接器的变量名称获取桥接器实例，其中"*APIConnector*"类型为String，表示桥接器的变量名称。  - ConnectorIns.process(renderCbk, errCbk)：通过桥接器实例调用process函数，主要作用为发起调用服务的请求和处理返回结果信息。 - 在通过process函数发起请求前，需设置桥接器实例的requestParams属性为请求的参数，例如：ConnectorIns.requestParams = param;  - 参数renderCbk，类型为Function，当返回结果信息后调用该函数，用于处理返回信息。  - 参数errCbk，类型为Function，调用该函数来处理错误。    - ConnectorIns.query(param)：通过桥接器实例调用process函数，主要作用为发起调用服务的请求和处理返回结果信息，参数说明如下： - param：请求参数。  - 其返回结果为Promise对象。    - getProperties：用于返回该组件的自定义属性值。 开发Widget时，可以给组件自定义属性，在开发界面可对这些属性进行配置，通过getProperties方法可返回自定义属性值。例如，var properties = thisObj.getProperties()。   - getContainer：用于返回渲染该组件的容器dom节点。 代码示例：var elem = thisObj.getContainer ()，然后通过jquery去查询组件中某个dom节点时，可通过$("#id", elem)的方式来获取。   - getWidgetBasePath：用于返回该组件静态资源的根路径。 例如某个组件的静态资源路径为"https://10.10.10.1:12900/default/0000000000NABzEjpNIH/assets/bundle/widget/172a6056501-a6f8ce1f-2ed9-4a9a-b883-251aaac14e0a/v1591923270914/test0609.js"，执行thisObj.getWidgetBasePath()返回"https://10.10.10.1:12900/default/0000000000NABzEjpNIH/assets/bundle/widget/172a6056501-a6f8ce1f-2ed9-4a9a-b883-251aaac14e0a/v1591923270914" 。   - getMessages：返回该组件国际化配置文件中定义的国际化文件内容。需要配置vue和vueI18n使用。 例如开发组件时定义了messages-en.json和messages-zh.json国际化文件。thisObj.getMessages()返回的就是这两个文件中定义的国际化内容。   - hideWidget：隐藏该组件的dom结构。在预览态调用该方法可以隐藏Widget。 例如，执行thisObj.hideWidget()方法隐藏该组件的dom结构。   - showWidget：显示该组件的dom结构。在预览态调用该方法可以展示Widget。 例如，执行thisObj.showWidget()方法显示该组件的dom结构。   - SITE_ROOT_PATH：为预置参数，用于获取当前站点URL地址的根路径。站点和应用是一对一的关系，当创建应用时，系统默认会创建并分配一个站点。 假如，某个页面的URL地址为"https://10.10.10.1:12900/magno/render/cool__app_0000000000NABzEjpNIH/page1"，则使用SITE_ROOT_PATH获取的根路径为"/magno/render/cool__app_0000000000NABzEjpNIH"。   - triggerEvent：用于触发事件，参数说明如下： - eventName：指定触发的事件名称。  - {}：为事件触发时传递的参数赋值，例如{param: value}。     |
      | Studio对象预置API     | - Studio.registerWidget：用来定义组件。  - Studio.registerConnector：用来定义桥接器。  - Studio.registerEvents：用于注册事件，只有通过此API注册后的事件才会在组件的事件列表中展现。参数说明如下： - thisObj：当前组件实例对象，指为该组件注册事件。  - eventName：事件名称，应该与触发事件API中的第一个参数保持一致。  - Event Label：事件标签名，在事件列表中展示的事件标题。  - \[\]：定义该事件触发时传递的参数模型，例如\[{"name": "param"}\] 。    - Studio.registerAction：用来注册动作。只有通过此API注册后的事件才会在组件的动作列表中展现。参数说明如下： - thisObj：当前组件实例对象，指为该组件注册动作。  - actionName：动作名称。  - Action Label：动作标签名，在动作列表中展示的动作标题。  - \[\]：事件触发时传入的参数。  - $.proxy(this.**receiveActionCbk**, this)：该动作的回调函数，在回调函数中定义该动作的执行逻辑。  - \[\]：此参数在开发过程中置为空数组即可。    - Studio.registerRouter：用来定义路由。  - Studio.inReader：判断当前高级页面状态是开发态或预览态。"true"表示在预览态（即运行态），"false"表示在开发态。  - StudioToolkit.getCatalogProperties()：用于获取当前站点的元数据。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
      | HttpUtils工具类预置API | 平台内置了HttpUtils工具类，预置API如下： - HttpUtils.getCookie：用于获取某个cookie的值。 代码示例：HttpUtils.getCookie()   - HttpUtils.setCookie：用于设置cookie的值。 代码示例：HttpUtils.setCookie("key","value")   - HttpUtils.getI18n：返回一个Vue18n的实例，配合Vue和VueI18n使用。该Vue18n实例可以在new一个Vue实例时赋值为i18n参数。 代码示例：HttpUtils.getI18n({locale: HttpUtils.getLocale(), messages: thisObj.getMessages()})     - HttpUtils.getCsrfToken：通过ajax的方式去调用平台的接口时使用。如果使用平台桥接器的方式，平台会自动在请求header中添加csfr-token头。 ``` HttpUtils.getCsrfToken(function(csrfToken) { $.ajax({ …. headers: { CSRF-Token: csrfToken }, }) }) ```   - HttpUtils.refreshToken：用于手动刷新页面的accesstoken，通常用在执行退出逻辑时，执行该方法刷新页面的accesstoken。  - HttpUtils.getUrlParam：用于获取查询字符串中的参数。 例如某个页面的URL为"https://10.10.10.1:12900/magno/render/cool__app_0000000000NABzEjpNIH/page1?param=1"，通过执行HttpUtils.getUrlParam("param")返回该参数的值"1"。   - HttpUtils.getLocalStorage：用于获取某个localStorage的值。 代码示例：HttpUtils.getLocalStorage("key")   - HttpUtils.setLocalStorage：用于设置某个localStorage的值。 代码示例：HttpUtils.setLocalStorage("key","value")                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
         
      
   
   7. 了解核心逻辑代码。
      - EchartsWidgetTemplate.js
        init()函数：组件初始化入口API，初始化组件通用能力，负责注册组件事件和组件动作。
        ```
        /*
           * 组件初始化入口API,初始化组件通用能力，负责注册组件事件和组件动作
           */
          init() {
            this._super.apply(this, arguments); // 组件通用能力构建，调用父类constructor,必须要写
            this.getWidgetI18n().then(() => this.render()); // 渲染组件
          },
        ```
        render()函数：组件核心渲染API，负责组件的实例化和数据调用，以及事件和动作的实际实现。
        ```
        /**
           * 组件核心渲染api，负责组件的实例化、数据调用及事件、动作的实际实现
           */
          render() {
            const widgetContainer = this.getContainer();
            if (!widgetContainer) return;
            this.initI18n();
            this.initReaderVm(this.getProps(), widgetContainer);
            this.registerWidgetActionAndEvent();
            this.registerResizeEvent(() => this?.readerVm?.echartsInst?.resize());
          },
        ```
        beforeDestroy()函数：组件销毁回调事件，负责组件在销毁期间的内存释放逻辑实现，需要把组件绑定的一些dom事件及全局的引用销毁。
        ```
        /**
           * 组件销毁回调事件，负责组件在销毁期间的内存释放逻辑实现，需要把组件绑定的一些dom事件及全局的引用销毁
           */
          beforeDestroy() {
            $(window).off('resize');
            this.readerVm && this.readerVm.$destroy && this.readerVm.$destroy();
          },
        ```
        initReaderVm()函数：初始化运行态组件VM实例。
        ```
        /**
           * 初始化运行态组件VM实例
           * @param {*} props 组件配置项
           * @param {*} widgetContainer 组件容器
           */
          initReaderVm(props, widgetContainer) {
            const { commonProps } = props;
            const thisObj = this;
            thisObj.readerVm = new window.Vue(...)
          },
        ```
        registerWidgetActionAndEvent()函数：注册组件对外暴露的事件和动作。
        ```
        /**
           * 注册组件对外暴露的事件和动作
           */
          registerWidgetActionAndEvent() {
            if (!window.Studio) {
              return;
            }
            window.Studio.registerEvents(this, 'clickSeries', { zh_CN: '点击系列', en_US: 'Click Series' });
            window.Studio.registerAction(
              this,
              'highlightSeries',
              { zh_CN: '高亮系列', en_US: 'Highlight Series' },
              [],
              (...args) => this.readerVm.highlightSeries(...args),
            );
          },
        ```
        
      
      - EchartsWidgetTemplate.ftl
        用于实现DOM结构，示例代码如下所示：
        ```
        <div id="EchartsWidgetTemplate" v-cloak>
          <div ref="echartsDom" class="echarts-container"></div>
        </div>
        ```
        
       
   
   
   
   
2. 对下载的模板进行重命名，本示例修改为BarGraph。 
   1. 进入解压后的目录，修改文件名称，即将EchartsWidgetTemplate.css修改为BarGraph.css，EchartsWidgetTemplate.editor.js修改为BarGraph.editor.js，EchartsWidgetTemplate.ftl修改为BarGraph.ftl，EchartsWidgetTemplate.js修改为BarGraph.js。
      图3修改后效果   
      ![](https://support.huaweicloud.com/usermanual-astrocanvas/zh-cn_image_0000002123186148.png) 
   
   2. 进入重名后的BarGraph.css文件，将组件ID替换为"BarGraph"，可通过搜索"EchartsWidgetTemplate"关键字进行批量替换。
      图4修改组件ID   
      ![](https://support.huaweicloud.com/usermanual-astrocanvas/zh-cn_image_0000002158426189.png) 
   
   3. 按照上述操作，替换BarGraph.editor.js、BarGraph.ftl、BarGraph.js和packageinfo.json文件中组件ID。 如果自定义组件需要在不同的语言环境下使用，messages-zh.json和messages-en.json文件中的"EchartsWidgetTemplate"关键字也请替换为"BarGraph"。
      
   
   
   
   
3. 完成上述操作后，将所有文件打成zip包（请直接打包，不要在文件夹外打包），且包名为"BarGraph.zip"。
 
