Newer
Older
smartwell_front / src / components / Amap / mixins / register-component.js
import upperCamelCase from 'uppercamelcase';
import { commonConvertMap } from '../utils/convert-helper';
import eventHelper from '../utils/event-helper';
import { lazyAMapApiLoaderInstance } from '../services/injected-amap-api-instance';
import VueAMap from '../';

export default {
  data() {
    return {
      unwatchFns: []
    };
  },

  mounted() {
    this.map = this.map || this.$parent.map;
    if (this.map) {
      this.register();
    } else {
      this.$on('ready', map => {
        this.map = map;
        this.register();
      });
    }
  },

  destroyed() {
    this.unregisterEvents();
    // if (!this.$amapComponent) return;
    //
    // this.$amapComponent.setMap && this.$amapComponent.setMap(null);
    // this.$amapComponent.close && this.$amapComponent.close();
    // this.$amapComponent.editor && this.$amapComponent.editor.close();
    // this.unwatchFns.forEach(item => item());
    // this.unwatchFns = [];
  },

  methods: {
    getHandlerFun(prop) {
      if (this.handlers && this.handlers[prop]) {
        return this.handlers[prop];
      }

      return this.$amapComponent[`set${upperCamelCase(prop)}`] || this.$amapComponent.setOptions;
    },
    // 转换参数,遍历所有props
    convertProps() {
      const props = {};
      if (this.map) props.map = this.map;
      const { $options: { propsData = {} }, propsRedirect } = this;
      return Object.keys(propsData).reduce((res, _key) => {
        let key = _key;
        let propsValue = this.convertSignalProp(key, propsData[key]);
        if (propsValue === undefined) return res;
        if (propsRedirect && propsRedirect[_key]) key = propsRedirect[key];
        props[key] = propsValue;
        return res;
      }, props);
    },
    // 转换特定属性
    convertSignalProp(key, sourceData) {
      let converter = '';
      let type = '';

      try {
        type = componentConfig.props[key];
        converter = commonConvertMap[type];
      } catch (e) {}
      // 如果该属性是需要转换的
      if (type && converter) {
        return converter(sourceData);
      } else if (this.converters && this.converters[key]) {
        return this.converters[key].call(this, sourceData);
      } else {
        const convertFn = commonConvertMap[key];
        if (convertFn) return convertFn(sourceData);
        return sourceData;
      }
    },
    // 注册事件
    registerEvents() {
      this.setEditorEvents && this.setEditorEvents();
      if (!this.$options.propsData) return;
      if (this.$options.propsData.events) {
        for (let eventName in this.events) {
          eventHelper.addListener(this.$amapComponent, eventName, this.events[eventName]);
        }
      }

      if (this.$options.propsData.onceEvents) {
        for (let eventName in this.onceEvents) {
          eventHelper.addListenerOnce(this.$amapComponent, eventName, this.onceEvents[eventName]);
        }
      }
    },
    // 清除事件注册
    unregisterEvents() {
      eventHelper.clearListeners(this.$amapComponent);
    },
    // 添加属性监听
    setPropWatchers() {
      const { propsRedirect, $options: { propsData = {} } } = this;

      Object.keys(propsData).forEach(prop => {
        let handleProp = prop;
        if (propsRedirect && propsRedirect[prop]) handleProp = propsRedirect[prop];
        let handleFun = this.getHandlerFun(handleProp);
        if (!handleFun && prop !== 'events') return;

        // watch props
        const unwatch = this.$watch(prop, nv => {
          if (prop === 'events') {
            this.unregisterEvents();
            this.registerEvents();
            return;
          }
          if (handleFun && handleFun === this.$amapComponent.setOptions) {
            return handleFun.call(this.$amapComponent, {[handleProp]: this.convertSignalProp(prop, nv)});
          }

          handleFun.call(this.$amapComponent, this.convertSignalProp(prop, nv));
        });

        // collect watchers for destroyed
        this.unwatchFns.push(unwatch);
      });
    },


    // some prop can not init by initial created methods
    // 一些不能再created时初始化的属性
    initProps() {
      const props = ['editable', 'visible'];

      props.forEach(propStr => {
        if (this[propStr] !== undefined) {
          const handleFun = this.getHandlerFun(propStr);
          handleFun && handleFun.call(this.$amapComponent, this.convertSignalProp(propStr, this[propStr]));
        }
      });
      this.printReactiveProp();
    },

    /**
     * methods for developing 开发用
     * find reactive props
     */
    printReactiveProp() {
      Object.keys(this._props).forEach(k => {
        let fn = this.$amapComponent[`set${upperCamelCase(k)}`];
        if (fn) {
          console.log(k);
        }
      });
    },
    // 注册组件
    register() {
      const res = this.__initComponent && this.__initComponent(this.convertProps());
      if (res && res.then) res.then((instance) => this.registerRest(instance));  // promise
      else this.registerRest(res);
    },
    // 注册接口
    registerRest(instance) {
      if (!this.$amapComponent && instance) this.$amapComponent = instance;
      this.registerEvents();
      this.initProps();
      this.setPropWatchers();

      if (this.events && this.events.init) {
        this.events.init(this.$amapComponent, this.map);
      }

    },

    // helper method
    $$getInstance() {
      return this.$amapComponent;
    }
  }
};