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

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

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

    万恶后端传过来的数据:
    "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  
       2021-06-18 16:00:10 +08:00
    为什么不直接让后端改下?
    happyCodings
        2
    happyCodings  
    OP
       2021-06-18 16:05:32 +08:00
    @yiqiao 后端傻瓜不改 想锤他
    meshell
        3
    meshell  
       2021-06-18 16:15:21 +08:00   ❤️ 4
    @happyCodings 我觉得这个确实不要后端改,前端自已转换所需要的结构
    AidenChen
        4
    AidenChen  
       2021-06-18 16:21:59 +08:00   ❤️ 4
    这个就是要前端改,后端始终提供列表以适应不同的展示需求;这里的处理实质上就是以根节点为最终父级,生成子孙树
    jenlors
        5
    jenlors  
       2021-06-18 16:23:28 +08:00   ❤️ 3
    后端没毛病
    xiangyuecn
        6
    xiangyuecn  
       2021-06-18 16:28:08 +08:00
    后端给平铺展开的数据(一层数组),数据库里面怎么存的就怎么拿,没毛病

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

    你这个递归几行代码就搞定了,也更容易理解,你倒好 for 也不写,reduce 有那么香吗?
    TomatoYuyuko
        7
    TomatoYuyuko  
       2021-06-18 16:34:09 +08:00   ❤️ 1
    这不是前端基本功嘛,生成树,面试都经常会遇到的题,自己写个工具类处理,递归几层就出来了。遇到这种问题不要硬循环,后面维护看到你人都麻了。。
    TomatoYuyuko
        8
    TomatoYuyuko  
       2021-06-18 16:38:35 +08:00
    前端数据处理直接用 lodash,我记得有现成的方法,你找找
    liyang5945
        9
    liyang5945  
       2021-06-18 16:39:25 +08:00
    你这个就两级吗,两级我有个简单的写法
    a719031256
        10
    a719031256  
       2021-06-18 16:39:32 +08:00
    @happyCodings
    这个不应该后端改,前几天还在给我配合的前端说这个事情
    前端需求变化很快,每次变化都要后端给前端再封装数据,就不方便了,还不如后端反你固定格式数据,前端按实际需求封装自己的需要的格式
    aguesuka
        11
    aguesuka  
       2021-06-18 16:39:44 +08:00
    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  
       2021-06-18 16:43:54 +08:00
    返回的数据结构如果也是后端改,那一个共用接口得写多少返回类型呀
    ccraohng
        13
    ccraohng  
       2021-06-18 16:48:15 +08:00
    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  
       2021-06-18 16:48:24 +08:00   ❤️ 1
    http://js.jsrun.net/RQVKp

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

    现在我全栈了,哪边简单方便哪边改。。。(现在贼怕 delay,deadline 就是第一生产力)
    ryncv
        16
    ryncv  
       2021-06-18 16:55:33 +08:00
    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  
       2021-06-18 16:55:49 +08:00
    看看 python 的 defaultDict,然后套两层嵌套的 defaultDict 就知道怎么做了
    timedivision
        18
    timedivision  
       2021-06-18 17:16:38 +08:00
    ``` 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));
    ```

    写的不是很好,但是应该可以满足你的需求
    lumotian
        19
    lumotian  
       2021-06-18 17:31:52 +08:00
    aitaii
        20
    aitaii  
       2021-06-18 17:38:55 +08:00
    友情提示:可以使用 gist 贴代码,这样代码格式会保留。
    lostpupil
        21
    lostpupil  
       2021-06-18 17:44:40 +08:00
    这后端返回的数据中规中矩,说人万恶谈不上。
    都是你写的代码属实是辣鸡没错。
    你一会儿 each 一会儿 reduce 一会儿 push 你到底想要 mute 还是 immute
    你这个用 lodash group map 改一下结构就行了。
    coderJie
        22
    coderJie  
       2021-06-18 17:57:07 +08:00
    我全栈开发,后端转换,前端转换我都试过,开发下来我觉得前端转化更合理。
    而且后端只是传了个正常的数据回来怎么就变成屎山代码了?
    molvqingtai
        23
    molvqingtai  
       2021-06-18 18:00:46 +08:00
    前端表示这不是常见的需求嘛
    lostpupil
        24
    lostpupil  
       2021-06-18 18:00:56 +08:00
    ```javascript
    city[ele[name]] =
    true &&
    item.push({
    ```
    lostpupil
        25
    lostpupil  
       2021-06-18 18:01:28 +08:00
    是什么原因让你写出了 true && 这种失了智的代码???
    Leviathann
        26
    Leviathann  
       2021-06-18 18:08:00 +08:00 via iPhone
    @aitaii 发贴可以选 markdown 模式
    sweetcola
        27
    sweetcola  
       2021-06-18 18:18:11 +08:00
    叠 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  
       2021-06-18 19:01:28 +08:00
    @happyCodings 他不改你帮他改啊
    cking
        29
    cking  
       2021-06-18 19:06:24 +08:00
    后端表示 我们不背这锅 这个返回已经算是很好的格式了
    renmu123
        30
    renmu123  
       2021-06-18 19:36:41 +08:00 via Android
    lodash groupby,但应该只支持两级。
    shuoshuxx
        31
    shuoshuxx  
       2021-06-18 19:43:21 +08:00
    后端觉得,这个格式就是正确的,后端不背锅
    Rache1
        32
    Rache1  
       2021-06-18 20:13:01 +08:00
    这些个前端,好不容从切图仔脱离了,又想回到切图仔日子
    learningman
        33
    learningman  
       2021-06-18 20:45:08 +08:00
    催公司上 GraphQL,想要啥格式有啥格式
    MoYi123
        34
    MoYi123  
       2021-06-18 22:19:44 +08:00
    就这样转一下格式都挠破脑袋,用 graphql 不是要被气哭
    Mitt
        35
    Mitt  
       2021-06-18 22:58:59 +08:00
    屎山代码指的是自己写的代码么?😹
    leyviw
        36
    leyviw  
       2021-06-18 23:26:01 +08:00 via iPhone
    后端就是返回标准的格式,给 N 个前端 N 个显示效果用,如果靠后端去兼容前端,那还得了
    aircjm
        37
    aircjm  
       2021-06-19 00:21:03 +08:00 via Android
    喷人家后端代码屎山 自己被喷的老惨了 😓
    icylogic
        38
    icylogic  
       2021-06-19 01:22:41 +08:00 via iPhone   ❤️ 4
    看了这贴最大的感受: @Livid 能不能改善一下 V2EX 评论贴代码的体验……
    medivh
        39
    medivh  
       2021-06-19 02:39:43 +08:00
    真·前端论坛
    grewer
        40
    grewer  
       2021-06-19 09:39:30 +08:00
    我看上面觉得后端没问题的不少啊, 这就前端论坛了...
    victor
        41
    victor  
       2021-06-19 10:09:00 +08:00
    先甩锅给后端,再来个红包钓鱼
    fewok
        42
    fewok  
       2021-06-19 10:30:58 +08:00
    就这,什么玩意
    ianva
        43
    ianva  
       2021-06-19 11:31:31 +08:00
    思路就是错的,代码写的再好也是屎山

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

    另外一个 map 数据的代码有啥值得优化的,明确输入和输出就完了,你代码是屎,别人要重构只了解输入和输出不看你逻辑就行了
    opengps
        44
    opengps  
       2021-06-19 11:33:52 +08:00
    怪不得前后端互相吐槽,这完全是各自都能处理的,除非这个接口是唯一用途可以后端去修改,否则宁肯提供多个也不应该修改输出结构,因为这种改法不符合开闭原则,是个新老不兼容的改动。前端是 web 还好,前端如果是 app,客户不升级停留在老版本岂不是必须强制下升级了
    ianva
        45
    ianva  
       2021-06-19 11:43:06 +08:00
    @opengps web 端可以在前端建模隔离接口变化,至于客户端更新的问题,在 BFF 建模隔离接口变化,当然都走 GraphQL 是最方便的
    anguiao
        46
    anguiao  
       2021-06-19 13:08:14 +08:00   ❤️ 2
    这帖子根本不想看,代码可读性太低了🤣
    CokeMine
        47
    CokeMine  
       2021-06-19 14:41:41 +08:00
    ganning
        48
    ganning  
       2021-06-19 15:12:24 +08:00
    @HashV2 哈哈哈哈,大佬
    LinHoo
        49
    LinHoo  
       2021-06-19 19:17:41 +08:00
    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  
       2021-06-20 08:32:54 +08:00
    个人认为这个后端出的结构代码没问题,自己解析。
    这层级算套的不错的了。
    happyCodings
        51
    happyCodings  
    OP
       2021-06-20 22:09:59 +08:00
    @coderJie 大佬我说我写的是 可能表述不清晰
    happyCodings
        52
    happyCodings  
    OP
       2021-06-20 22:13:27 +08:00
    @meshell 大佬们统一回复一下 是我自己写的代码像屎山,然后想优化一下,实力原因来求助
    ps:刚毕业的前端小码农
    谢谢大佬们
    happyCodings
        53
    happyCodings  
    OP
       2021-06-20 22:13:35 +08:00
    @aguesuka 谢谢大佬
    happyCodings
        54
    happyCodings  
    OP
       2021-06-20 22:13:57 +08:00
    @ccraohng 谢谢大佬
    happyCodings
        55
    happyCodings  
    OP
       2021-06-20 22:14:06 +08:00
    @ryncv 谢谢大佬
    happyCodings
        56
    happyCodings  
    OP
       2021-06-20 22:14:16 +08:00
    @timedivision 谢谢大佬
    happyCodings
        57
    happyCodings  
    OP
       2021-06-20 22:15:15 +08:00
    @CokeMine 谢谢大佬
    happyCodings
        58
    happyCodings  
    OP
       2021-06-20 22:15:29 +08:00
    @LinHoo 谢谢大佬
    vueli
        59
    vueli  
       2021-06-21 10:05:34 +08:00
    为什么不写在。``` ``` 里面, 看着好难受. 又懒不想拿过来运行格式化
    Cy1
        60
    Cy1  
       2021-06-21 11:08:27 +08:00
    后端这格式不是很合理么,真就什么数据都处理好,前端直接套才算合理么?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5969 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 02:02 · PVG 10:02 · LAX 18:02 · JFK 21:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.