Home Reference Source

src/plugins/PropertyPlugin.js

/**
 * @file 属性插件
 * @author exodia(d_xinxin@163.com)
 */

import u from '../util';
import BasePlugin from './BasePlugin';

const CACHE = Symbol('cache');

/**
 * @private
 */
export default class PropertyPlugin extends BasePlugin {
    static getSetter(obj) {
        if (u.isObject(obj) && typeof obj.$setter === 'string') {
            return obj.$setter;
        }
    }

    static setProperty(instance, propertyName, value, setterName) {
        if (setterName) {
            return instance[setterName](value);
        }

        let method = 'set' + propertyName.charAt(0).toUpperCase() + propertyName.slice(1);
        typeof instance[method] === 'function' ? instance[method](value) : (instance[propertyName] = value);
    }

    get name() {
        return 'property';
    }

    constructor() {
        super();
        this[CACHE] = Object.create(null);
    }

    /**
     * @override
     */
    afterCreateInstance(ioc, componentId, instance) {
        if (!ioc.hasComponent(componentId)) {
            return Promise.resolve(instance);
        }

        let config = ioc.getComponentConfig(componentId);
        let deps = this.resolveDependencies(ioc, componentId);
        let props = config.properties;
        return ioc.getComponent(deps).then(
            components => {
                for (let k in props) {
                    let property = props[k];
                    let value = u.hasRef(property) ? components[deps.indexOf(property.$ref)] : property;
                    PropertyPlugin.setProperty(instance, k, value, PropertyPlugin.getSetter(property));
                }
                return instance;
            }
        );
    }

    resolveDependencies(ioc, id) {
        if (this[CACHE][id]) {
            return this[CACHE][id];
        }

        let deps = this[CACHE][id] = [];
        let config = ioc.getComponentConfig(id);
        let properties = config.properties;
        for (let k in properties) {
            let property = properties[k];
            u.hasRef(property) && deps.push(property.$ref);
        }

        config.propDeps = deps;

        return deps;
    }
}