V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vue.js
happyCodings
V2EX  ›  Vue.js

求大佬们优化一下代码,屎山代码给孩子头皮想破了

  •  
  •   happyCodings · 48 天前 · 6380 次点击
    这是一个创建于 48 天前的主题,其中的信息可能已经有所发展或是发生改变。
    秉着不写垃圾代码的原则,求大佬优化一下,最优值奉上红包
    需求是这样的:

    万恶后端传过来的数据:
    "data":[{"province":"上海市","city":"上海市市辖区","adcode":"310118","district":"青浦区"},
    {"province":"江苏","city":"苏州市","adcode":"320506","district":"吴中区"},
    {"province":"山西省","city":"阳泉市","adcode":"140302","district":"城区"},
    {"province":"上海市","city":"上海市市辖区","adcode":"310101","district":"黄浦区"},
    {"province":"河北省","city":"石家庄市","adcode":"130123","district":"正定县"}]

    需要整合成这样 elementUi 中级联选择器中的数据:
    (只要有相同的就要去重并在之前的 children 下加入重复的 children )
    addressOptions: [
    {
    value: "zhinan",
    label: "指南",
    children: [
    {
    value: "shejiyuanze",
    label: "设计原则",
    children: [
    {
    value: "yizhi",
    label: "一致",
    },
    {
    value: "fankui",
    label: "反馈",
    },
    {
    value: "xiaolv",
    label: "效率",
    },
    {
    value: "kekong",
    label: "可控",
    },
    ],
    },
    {
    value: "daohang",
    label: "导航",
    children: [
    {
    value: "cexiangdaohang",
    label: "侧向导航",
    },
    {
    value: "dingbudaohang",
    label: "顶部导航",
    },
    ],
    },
    ],
    },
    ],

    我的垃圾代码:

    dealWithAddressList(arr, name) {
    var city = {};
    return arr.reduce(function (item, ele) {
    console.log(ele[name]);
    if (city[ele[name]]) {
    item.forEach((eles) => {
    if (eles.label == ele[name]) {
    eles.children.forEach((eless) => {
    if (eless.value == ele.city) {
    eless.children.push({
    value: ele.adcode,
    label: ele.district,
    });
    } else {
    eles.children.push({
    value: ele.city,
    label: ele.city,
    children: [
    {
    value: ele.adcode,
    label: ele.district,
    },
    ],
    });
    }
    });
    }
    });
    console.log(city[ele[name]]);
    } else {
    city[ele[name]] =
    true &&
    item.push({
    value: ele.province,
    label: ele.province,
    children: [
    {
    value: ele.city,
    label: ele.city,
    children: [
    {
    value: ele.adcode,
    label: ele.district,
    },
    ],
    },
    ],
    });
    }
    console.log(item);
    return item;
    }, []);
    },

    求大佬优化一下,可以的话有红包奉上
    60 条回复    2021-06-21 11:08:27 +08:00
    yiqiao
        1
    yiqiao   48 天前
    为什么不直接让后端改下?
    happyCodings
        2
    happyCodings   48 天前
    @yiqiao 后端傻瓜不改 想锤他
    meshell
        3
    meshell   48 天前   ❤️ 4
    @happyCodings 我觉得这个确实不要后端改,前端自已转换所需要的结构
    AidenChen
        4
    AidenChen   48 天前   ❤️ 4
    这个就是要前端改,后端始终提供列表以适应不同的展示需求;这里的处理实质上就是以根节点为最终父级,生成子孙树
    long2ice
        5
    long2ice   48 天前   ❤️ 3
    后端没毛病
    xiangyuecn
        6
    xiangyuecn   48 天前
    后端给平铺展开的数据(一层数组),数据库里面怎么存的就怎么拿,没毛病

    结构格式化,js 很容易(简洁),大部分后端语言很困难(蹩脚难看)

    你这个递归几行代码就搞定了,也更容易理解,你倒好 for 也不写,reduce 有那么香吗?
    TomatoYuyuko
        7
    TomatoYuyuko   48 天前   ❤️ 1
    这不是前端基本功嘛,生成树,面试都经常会遇到的题,自己写个工具类处理,递归几层就出来了。遇到这种问题不要硬循环,后面维护看到你人都麻了。。
    TomatoYuyuko
        8
    TomatoYuyuko   48 天前
    前端数据处理直接用 lodash,我记得有现成的方法,你找找
    liyang5945
        9
    liyang5945   48 天前
    你这个就两级吗,两级我有个简单的写法
    a719031256
        10
    a719031256   48 天前
    @happyCodings
    这个不应该后端改,前几天还在给我配合的前端说这个事情
    前端需求变化很快,每次变化都要后端给前端再封装数据,就不方便了,还不如后端反你固定格式数据,前端按实际需求封装自己的需要的格式
    aguesuka
        11
    aguesuka   48 天前
    class Address {
    /**
    * @type string
    */
    province

    /**
    * @type string
    */
    city

    /**
    * @type string
    */
    adcode

    /**
    * @type string
    */
    district
    }

    class TreeNode {
    /**
    * @type string
    */
    value
    /**
    * @type string
    */
    label

    /**
    * @type TreeNode[]
    */
    children
    }

    /**
    *
    * @param addresses {Address[]}
    * @return TreeNode[]
    */
    function dealWithAddressList(addresses) {
    /**
    * @type {TreeNode[]}
    */
    const result = []
    /**
    *
    * @type {Map<string, TreeNode>}
    */
    const createdElements = new Map()
    /**
    *
    * @param value {string}
    * @param brothers {TreeNode[]}
    * @returns {TreeNode}
    */
    const nodeOf = (value, brothers) => {
    let node = createdElements.get(value);
    if (node === undefined) {
    node = {
    children: [],
    value: value,
    label: value,
    }
    brothers.push(node)
    createdElements.set(value, node)
    }
    return node
    }

    for (let address of addresses) {
    let provinceNode = nodeOf(address.province, result)
    let cityNode = nodeOf(address.city, provinceNode.children);
    cityNode.children.push({
    children: [],
    value: address.adcode,
    label: address.district,
    })
    }
    return result;
    }

    function test() {
    return dealWithAddressList([{"province": "上海市", "city": "上海市市辖区", "adcode": "310118", "district": "青浦区"},
    {"province": "江苏", "city": "苏州市", "adcode": "320506", "district": "吴中区"},
    {"province": "山西省", "city": "阳泉市", "adcode": "140302", "district": "城区"},
    {"province": "上海市", "city": "上海市市辖区", "adcode": "310101", "district": "黄浦区"},
    {"province": "河北省", "city": "石家庄市", "adcode": "130123", "district": "正定县"}]);
    }

    test()
    zhangchongjie
        12
    zhangchongjie   48 天前
    返回的数据结构如果也是后端改,那一个共用接口得写多少返回类型呀
    ccraohng
        13
    ccraohng   48 天前
    function convert() {
    const levels = ['province', 'city', 'district'];
    const result = {
    children: {},
    };

    data.forEach((item) => {
    levels.reduce((map, level) => {
    const current = item[level];

    if (!map.children) {
    map.children = {};
    }

    map.children[current] = map.children[current] || {
    data: {
    label: current,
    value: level === 'district' ? item.adcode : current,
    },
    };

    return map.children[current];
    }, result);
    });

    const format = (item) => {
    if (item.children) {
    const children = Object.values(item.children).map((child) => {
    return format(child);
    });

    item.children = children;
    }

    return item;
    };

    const root = format(result).children;
    console.log(root);
    }
    convert();
    Vegetable
        14
    Vegetable   48 天前   ❤️ 1
    http://js.jsrun.net/RQVKp

    处理省市区什么的写的比较难看,大概就是这个思路吧
    通过一个 hash 做映射,方便找到父节点
    HashV2
        15
    HashV2   48 天前
    我做后端的时候都是前端来改结构,我做前端的时候都是后端来改结构(因为我比较能喷,而且不怕 delay )

    现在我全栈了,哪边简单方便哪边改。。。(现在贼怕 delay,deadline 就是第一生产力)
    ryncv
        16
    ryncv   48 天前
    O(1)复杂度
    ```javascript
    const data =[{"province":"上海市","city":"上海市市辖区","adcode":"310118","district":"青浦区"},
    {"province":"江苏","city":"苏州市","adcode":"320506","district":"吴中区"},
    {"province":"山西省","city":"阳泉市","adcode":"140302","district":"城区"},
    {"province":"上海市","city":"上海市市辖区","adcode":"310101","district":"黄浦区"},
    {"province":"河北省","city":"石家庄市","adcode":"130123","district":"正定县"}];

    function listToTree(list) {
    const map = {};
    list.forEach(({province, city, district, adcode}) => {
    const item = {name: district, value: adcode};
    if (!map[province]) {
    map[province] = {
    name: province,
    children: [{
    name: city,
    children: [item]
    }]
    }
    return;
    }
    const cityItem = map[province].children.find(one => one.name === city);
    if (!cityItem) {
    map[province].children.push({ name: city,children: [item]})
    } else {
    cityItem.children.push(item);
    }
    })
    return Object.values(map);
    }

    console.log(listToTree(data));
    ```
    bnm965321
        17
    bnm965321   48 天前
    看看 python 的 defaultDict,然后套两层嵌套的 defaultDict 就知道怎么做了
    timedivision
        18
    timedivision   48 天前
    ``` js
    const data = [
    {
    province: '上海市',
    city: '上海市市辖区',
    adcode: '310118',
    district: '青浦区',
    },
    { province: '江苏', city: '苏州市', adcode: '320506', district: '吴中区' },
    { province: '山西省', city: '阳泉市', adcode: '140302', district: '城区' },
    {
    province: '上海市',
    city: '上海市市辖区',
    adcode: '310101',
    district: '黄浦区',
    },
    {
    province: '河北省',
    city: '石家庄市',
    adcode: '130123',
    district: '正定县',
    },
    ];

    const pObj = {};
    const cObj = {};
    data.forEach(item => {
    const { province, city } = item;
    if (pObj[province]) {
    pObj[province].push(item);
    } else {
    pObj[province] = [item];
    }
    if (cObj[city]) {
    cObj[city].push(item);
    } else {
    cObj[city] = [item];
    }
    });
    const proValue = Object.values(pObj);
    const cityKey = Object.keys(cObj);
    const res = [];
    proValue.forEach(pro => {
    cityKey.forEach(key => {
    if (pro[0] && key === pro[0].city) {
    res.push({
    value: pro[0].adcode,
    label: pro[0].province,
    children: [
    {
    label: key,
    value: pro[0].adcode,
    children: cObj[key].map(dis => {
    return {
    label: dis.district,
    value: pro[0].adcode,
    };
    }),
    },
    ],
    });
    }
    });
    });
    console.log(JSON.stringify(res));
    ```

    写的不是很好,但是应该可以满足你的需求
    aitaii
        20
    aitaii   48 天前
    友情提示:可以使用 gist 贴代码,这样代码格式会保留。
    lostpupil
        21
    lostpupil   48 天前
    这后端返回的数据中规中矩,说人万恶谈不上。
    都是你写的代码属实是辣鸡没错。
    你一会儿 each 一会儿 reduce 一会儿 push 你到底想要 mute 还是 immute
    你这个用 lodash group map 改一下结构就行了。
    coderJie
        22
    coderJie   48 天前
    我全栈开发,后端转换,前端转换我都试过,开发下来我觉得前端转化更合理。
    而且后端只是传了个正常的数据回来怎么就变成屎山代码了?
    molvqingtai
        23
    molvqingtai   48 天前
    前端表示这不是常见的需求嘛
    lostpupil
        24
    lostpupil   48 天前
    ```javascript
    city[ele[name]] =
    true &&
    item.push({
    ```
    lostpupil
        25
    lostpupil   48 天前
    是什么原因让你写出了 true && 这种失了智的代码???
    Leviathann
        26
    Leviathann   48 天前 via iPhone
    @aitaii 发贴可以选 markdown 模式
    sweetcola
        27
    sweetcola   48 天前
    叠 buff 的来了(仅供娱乐)

    const data =[{"province":"上海市","city":"上海市市辖区","adcode":"310118","district":"青浦区"},
    {"province":"江苏","city":"苏州市","adcode":"320506","district":"吴中区"},
    {"province":"山西省","city":"阳泉市","adcode":"140302","district":"城区"},
    {"province":"上海市","city":"上海市市辖区","adcode":"310101","district":"黄浦区"},
    {"province":"河北省","city":"石家庄市","adcode":"130123","district":"正定县"}];

    var obj = Object.keys(obj = data.reduce((t, c) => ({ ...t, [c.province]: { ...t[c.province], [c.city]: { ...t[c.province]?.[c.city], [c.district]: c.adcode } } }), {})).map((v) => ({ name: v, children: Object.keys(obj[v]).map((v1) => ({name: v1, children: Object.keys(obj[v][v1]).map((v2) => ({ name: v2, value: obj[v][v1][v2]})) })) }));

    console.log(obj);
    darknoll
        28
    darknoll   48 天前
    @happyCodings 他不改你帮他改啊
    cking
        29
    cking   48 天前
    后端表示 我们不背这锅 这个返回已经算是很好的格式了
    renmu123
        30
    renmu123   48 天前 via Android
    lodash groupby,但应该只支持两级。
    shuoshuxx
        31
    shuoshuxx   48 天前
    后端觉得,这个格式就是正确的,后端不背锅
    Rache1
        32
    Rache1   47 天前
    这些个前端,好不容从切图仔脱离了,又想回到切图仔日子
    learningman
        33
    learningman   47 天前
    催公司上 GraphQL,想要啥格式有啥格式
    MoYi123
        34
    MoYi123   47 天前
    就这样转一下格式都挠破脑袋,用 graphql 不是要被气哭
    Mitt
        35
    Mitt   47 天前
    屎山代码指的是自己写的代码么?😹
    leyviw
        36
    leyviw   47 天前 via iPhone
    后端就是返回标准的格式,给 N 个前端 N 个显示效果用,如果靠后端去兼容前端,那还得了
    aircjm
        37
    aircjm   47 天前 via Android
    喷人家后端代码屎山 自己被喷的老惨了 😓
    icylogic
        38
    icylogic   47 天前 via iPhone   ❤️ 4
    看了这贴最大的感受: @Livid 能不能改善一下 V2EX 评论贴代码的体验……
    medivh
        39
    medivh   47 天前
    真·前端论坛
    grewer
        40
    grewer   47 天前
    我看上面觉得后端没问题的不少啊, 这就前端论坛了...
    victor
        41
    victor   47 天前
    先甩锅给后端,再来个红包钓鱼
    fewok
        42
    fewok   47 天前
    就这,什么玩意
    ianva
        43
    ianva   47 天前
    思路就是错的,代码写的再好也是屎山

    接口和 组件 porps 的变化怎么隔离?不隔离接口一变,你代码也跟着变?组件换了这套代码再来一遍?一个需求变化就得重写的东西

    另外一个 map 数据的代码有啥值得优化的,明确输入和输出就完了,你代码是屎,别人要重构只了解输入和输出不看你逻辑就行了
    opengps
        44
    opengps   47 天前
    怪不得前后端互相吐槽,这完全是各自都能处理的,除非这个接口是唯一用途可以后端去修改,否则宁肯提供多个也不应该修改输出结构,因为这种改法不符合开闭原则,是个新老不兼容的改动。前端是 web 还好,前端如果是 app,客户不升级停留在老版本岂不是必须强制下升级了
    ianva
        45
    ianva   47 天前
    @opengps web 端可以在前端建模隔离接口变化,至于客户端更新的问题,在 BFF 建模隔离接口变化,当然都走 GraphQL 是最方便的
    anguiao
        46
    anguiao   47 天前   ❤️ 2
    这帖子根本不想看,代码可读性太低了🤣
    CokeMine
        47
    CokeMine   47 天前
    ganning
        48
    ganning   47 天前
    @HashV2 哈哈哈哈,大佬
    LinHoo
        49
    LinHoo   47 天前
    const convert = data => {
    const options = []
    const proviceMap = {}
    data.forEach(item => {
    // 没有省
    if (!proviceMap[item.province]) {
    proviceMap[item.province] = {
    index: options.length,
    citys: [item.city]
    }
    options.push({
    value: item.province,
    label: item.province,
    children: [
    {
    value: item.city,
    label: item.city,
    children: [
    {
    value: item.adcode,
    label: item.district,
    }
    ]
    }
    ]
    })
    return
    }

    const provinceIndex = proviceMap[item.province].index
    const cityIndex = proviceMap[item.province].citys.indexOf(item.city)
    // 没有市
    if (cityIndex === -1) {
    options[provinceIndex].children.push({
    value: item.city,
    label: item.city,
    children: [
    {
    value: item.adcode,
    label: item.district,
    }
    ]
    })
    return
    }
    // 有省有市
    options[provinceIndex].children[cityIndex].children.push({
    value: item.adcode,
    label: item.district,
    })
    })
    }
    DeWjjj
        50
    DeWjjj   46 天前
    个人认为这个后端出的结构代码没问题,自己解析。
    这层级算套的不错的了。
    happyCodings
        51
    happyCodings   45 天前
    @coderJie 大佬我说我写的是 可能表述不清晰
    happyCodings
        52
    happyCodings   45 天前
    @meshell 大佬们统一回复一下 是我自己写的代码像屎山,然后想优化一下,实力原因来求助
    ps:刚毕业的前端小码农
    谢谢大佬们
    happyCodings
        53
    happyCodings   45 天前
    @aguesuka 谢谢大佬
    happyCodings
        54
    happyCodings   45 天前
    @ccraohng 谢谢大佬
    happyCodings
        55
    happyCodings   45 天前
    @ryncv 谢谢大佬
    happyCodings
        56
    happyCodings   45 天前
    @timedivision 谢谢大佬
    happyCodings
        57
    happyCodings   45 天前
    @CokeMine 谢谢大佬
    happyCodings
        58
    happyCodings   45 天前
    @LinHoo 谢谢大佬
    vueli
        59
    vueli   45 天前
    为什么不写在。``` ``` 里面, 看着好难受. 又懒不想拿过来运行格式化
    Cy1
        60
    Cy1   45 天前
    后端这格式不是很合理么,真就什么数据都处理好,前端直接套才算合理么?
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2452 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:12 · PVG 20:12 · LAX 05:12 · JFK 08:12
    ♥ Do have faith in what you're doing.