
# {widget}.js
#### 文件介绍
*{widget}* .js为组件逻辑文件，整个Widget的渲染核心JS，在组件编辑状态和页面最终的发布运行态都会被加载执行。一个推荐的组件架构，应包含[表1]中API。其中，init、render和beforeDestroy为组件的通用生命周期函数，其余为推荐模板实现。
 表1组件架构组成 
| API名称                        | API解释                                                                                                                                         | 是否必须               |
|:---|:---|:---|
| init(生命周期函数)                 | 组件初始化入口API，初始化组件通用能力，负责注册组件事件和组件动作。                                                                                                           | 是                  |
| render(生命周期函数)               | 组件核心渲染API，负责组件的实例化、数据调用及事件、动作的实际实现。                                                                                                           | 是                  |
| beforeDestroy(生命周期函数)        | 组件销毁回调事件，负责组件在销毁期间的内存释放逻辑实现，需要把组件绑定的一些dom事件及全局的引用销毁。                                                                                          | 是                  |
| initContainer                | render中抽取的独立逻辑，初始化组件container，所有组件逻辑统一。                                                                                                       | 统一实现，无需改动。         |
| getInitProps                 | render中抽取的独立逻辑，基于默认prop和组件配置的props进行融合处理，并返回。                                                                                                 | 建议实现。              |
| initI18n                     | 初始化组件message-en/message-zh的多语言信息，统一注册到独立的i18nVue实例中，供组件获取桩数据、获取默认配置、初始化组件统一使用。                                                                | 建议实现。              |
| initReaderVm                 | render中抽取的独立逻辑，初始化运行态组件VM实例。在实例中获取数据并实现组件的核心渲染。                                                                                               | 建议实现。              |
| registerWidgetActionAndEvent | init中抽取的独立逻辑，注册组件对外暴露的事件和动作。                                                                                                                  | 按需实现，组件定义事件和动作时使用。 |
| getMockData                  | 组件在没有对接外部数据源时，使用的获取桩数据的API自定义实现。考虑数据集天然支持二维数组对象，桩数据结构统一为二维数组对象\[{id:3,name:'zhangsan'}\]。某些场景假如只需要一个简单值val，可以设置组件桩数据设置为简单二维对象数组\[{val:123}\]。 | -                  |
   
#### 文件示例
- 通用的组件核心代码
  ```
  var EchartsWidgetTemplate = StudioWidgetWrapper.extend({
    /*
     * 组件初始化入口API,初始化组件通用能力，负责注册组件事件和组件动作
     */
    init() {},
    /**
     * 组件核心渲染api，负责组件的实例化、数据调用及事件、动作的实际实现
     */
    render() {},
    /**
     * 组件销毁回调事件，负责组件在销毁期间的内存释放逻辑实现，需要把组件绑定的一些dom事件及全局的引用销毁
     */
    beforeDestroy() {},
      /**
       * 统一获取组件桩数据，建议实现
       */
      getMockData() {},
  })
  ```
  
- 组件的整体代码
  ```
  var EchartsWidgetTemplate = StudioWidgetWrapper.extend({
    /*
     * 组件初始化入口API,初始化组件通用能力，负责注册组件事件和组件动作
     */
    init() {
      this._super.apply(this, arguments); // 组件通用能力构建，调用父类constructor,必须要写
      this.getWidgetI18n().then(() => this.render()); // 渲染组件
    },
    /**
     * 组件核心渲染api，负责组件的实例化、数据调用及事件、动作的实际实现
     */
    render() {
      const widgetContainer = this.getContainer();
      if (!widgetContainer) return;
      this.initI18n();
      this.initReaderVm(this.getProps(), widgetContainer);
      this.registerWidgetActionAndEvent();
      this.registerResizeEvent(() => this?.readerVm?.echartsInst?.resize());
    },
    /**
     * 组件销毁回调事件，负责组件在销毁期间的内存释放逻辑实现，需要把组件绑定的一些dom事件及全局的引用销毁
     */
    beforeDestroy() {
      $(window).off('resize');
      this.readerVm && this.readerVm.$destroy && this.readerVm.$destroy();
    },
    /**
     *
     * @returns 初始化组件message-en,message-zh的多语言信息，统一注册到独立的i18nVue实例中。供组件获取桩数据、获取默认配置、初始化组件统一使用
     */
    initI18n() {
      const i18n = window.HttpUtils.getI18n({
        locale: window.HttpUtils.getLocale(),
        messages: this.getMessages(),
      });
      const i18nVM = new window.Vue({ i18n });
      this.$t = (key) => i18nVM.$t(key);
    },
    getProps() {
      const props = this.getProperties() || {};
      const commonProps = $.extend(
        true,
        {},
        { emphasisFocus: 'series', showLabel: true, axisPointerType: 'shadow' },
        JSON.parse(props.commonProps || '{}'),
      );
      return { commonProps };
    },
    /**
     * 初始化运行态组件VM实例
     * @param {*} props 组件配置项
     * @param {*} widgetContainer 组件容器
     */
    initReaderVm(props, widgetContainer) {
      const { commonProps } = props;
      const thisObj = this;
      thisObj.readerVm = new window.Vue({
        el: $('#EchartsWidgetTemplate', widgetContainer)[0],
        data() {
          return {
            commonProps,
            dataValue: [],
            echartsInst: null,
            ConnectorIns: thisObj.getConnectorInstanceByName('EchartsWidgetTemplateConnector') || '',
          };
        },
        mounted() {
          this.echartsInst = window.echarts.init(this.$refs.echartsDom);
          this.echartsInst.on('click', 'series', (event) => {
            thisObj.triggerEvent('clickSeries', event);
          });
          thisObj.callFlowConn(this.ConnectorIns, {}, (res) => {
            this.dataValue = res;
            this.drawEcharts();
          });
        },
        methods: {
          drawEcharts() {
            const dataX = [...new Set(this.dataValue.map((row) => row.x))];
            this.echartsInst.setOption({
              xAxis: {
                type: 'category',
                data: dataX,
              },
              yAxis: {
                type: 'value',
              },
              series: [...new Set(this.dataValue.map((row) => row.s))].map((key) => ({
                data: dataX.map((x) => this.dataValue.find((item) => item.x === x && item.s === key)?.y),
                name: key,
                type: 'bar',
                emphasis: { focus: this.commonProps.emphasisFocus },
                label: {
                  show: this.commonProps.showLabel,
                  distance: this.commonProps.labelDistance,
                },
              })),
              tooltip: {
                trigger: 'axis',
                axisPointer: { type: this.commonProps.axisPointerType },
              },
            });
          },
          highlightSeries({ eventParam }) {
            this.echartsInst.dispatchAction({ type: 'highlight', seriesIndex: eventParam.seriesIndex });
          },
        },
      });
    },
    /**
     * 注册组件对外暴露的事件和动作
     */
    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),
      );
    },
    /**
     * 自定义api，组件在没有对接外部数据源时使用的桩数据，桩数据结构统一为二维数组对象
     * @returns [{}]
     */
    getMockData() {
      const seviceWaterLevel = this.$t('setting.seviceWaterLevel');
      const seviceLoad = this.$t('setting.seviceLoad');
      return [
        {
          x: '00:00',
          y: 11.69,
          s: seviceWaterLevel,
        },
        {
          x: '02:30',
          y: 17.46,
          s: seviceWaterLevel,
        },
        {
          x: '05:00',
          y: 28.57,
          s: seviceWaterLevel,
        },
        {
          x: '07:30',
          y: 12.7,
          s: seviceWaterLevel,
        },
        {
          x: '10:00',
          y: 18.99,
          s: seviceWaterLevel,
        },
        {
          x: '12:30',
          y: 3.7,
          s: seviceWaterLevel,
        },
        {
          x: '15:00',
          y: 18.52,
          s: seviceWaterLevel,
        },
        {
          x: '17:30',
          y: 23.81,
          s: seviceWaterLevel,
        },
        {
          x: '20:00',
          y: 10.58,
          s: seviceWaterLevel,
        },
        {
          x: '22:30',
          y: 15.82,
          s: seviceWaterLevel,
        },
        {
          x: '24:00',
          y: 3.76,
          s: seviceWaterLevel,
        },
        {
          x: '00:00',
          y: 5.69,
          s: seviceLoad,
        },
        {
          x: '02:30',
          y: 12.46,
          s: seviceLoad,
        },
        {
          x: '05:00',
          y: 18.57,
          s: seviceLoad,
        },
        {
          x: '07:30',
          y: 25.7,
          s: seviceLoad,
        },
        {
          x: '10:00',
          y: 13.99,
          s: seviceLoad,
        },
        {
          x: '12:30',
          y: 9.7,
          s: seviceLoad,
        },
        {
          x: '15:00',
          y: 20.52,
          s: seviceLoad,
        },
        {
          x: '17:30',
          y: 28.81,
          s: seviceLoad,
        },
        {
          x: '20:00',
          y: 15.58,
          s: seviceLoad,
        },
        {
          x: '22:30',
          y: 19.82,
          s: seviceLoad,
        },
        {
          x: '24:00',
          y: 9.76,
          s: seviceLoad,
        },
      ];
    },
  });
  ```
  
 
