前端 DTO 实践

103 阅读1分钟

后台系统的前后端字段不一样,前端用的是小驼峰,后端用的是下划线分隔,每次转起来特别烦,所以想着写个简单的 dto 来转换一下。同时还可以用自定义的规则来判断字段的过滤,不通过就不传给后端。

export class AdvancedDtoManager {  
    constructor(source = {}, validationRules = {}, mappingRules = {}) {  
        this.source = source;  
        this.validationRules = validationRules;  
        this.mappingRules = mappingRules;  
    }  

    validate(key, value) {  
        const rule = this.validationRules[key];  
        if (!rule) {  
            return true;  
        }  
        return rule(value);  
    }  

    toDto() {  
        const dto = {};  
        for (const key in this.source) {  
            if (this.validate(key, this.source[key])) {  
                const mappedKey = this.mappingRules[key] || key;  
                dto[mappedKey] = this.source[key];  
            }  
        }  
        return dto;  
    }  

    fromDto(dto) {  
        const source = {};  
        for (const key in dto) {  
            const reverseMapping = Object.entries(this.mappingRules).find(  
            ([, v]) => v === key  
            )?.[0] || key;  
            if (this.validate(reverseMapping, dto[key])) {  
                source[reverseMapping] = dto[key];  
            }  
        }  
        return source;  
    }  
}  
  
  
function isDefined(v) {  
    return v !== undefined && v !== null;  
}  
  
function notEmptyArr(v) {  
    return v && v.length > 0;  
}  
  
function isNumber(v) {  
    return (typeof v === 'number' || v) && !isNaN(v);  
}  
  
function isValidNumber(v) {  
    return isNumber(v) && v > 0;  
}  
  
function isString(v) {  
    return typeof v === 'string';  
}

export const rules = {  
    name: isDefined,  
    groupId: isDefined,  
    tags: notEmptyArr,    
    coverUrl: isDefined,  
    id: isString,
};

export const mapping = {  
    'name': 'name',  
    'groupId': 'group_id',  
    'assetType': 'asset_type',  
    'coverUrl': 'cover_url',    
    'id': 'asset_id',  
    'tags': 'tags'
};

业务层使用方式如下

const manager = new AdvancedDtoManager(data, rules, mapping);  
const Dto = manager.toDto();