对象和数组神奇之处转换/转换业务场景

对象和数组神奇之处转换

在平常开发中,需要数组和对象直接转换,方便我们找对应属性的数据

数组 => 对象

  • 场景一 : 当后台返回一个数据字典的数据,我们要根据数据字典的value,显示对应的label
    let arr = [
        {
            id: "001",
            dictLabel: "男",
            dictValue: 1
        },
        {
            id: "002",
            dictLabel: "女",
            dictValue: 2
        },
        {
            id: "003",
            dictLabel: "未知",
            dictValue: 0
        }
    ]

    let sexOptions = arr.reduce((pre,cur) => {
        pre[cur.dictValue] = cur.dictLabel
        return pre;
    }, {})
    console.log(sexOptions)
//{0: "未知", 1: "男", 2: "女"}
  • 场景二: 当后台返回一个 线性结构的数据, 但是我们前端树形组件需要树形结构的数据,去显示树形组件。
  • 正常使用
let arr = [
{
    id:1,
    name:"zs"
  },
  {
    id:2,
    name: "ls"
  }
]
//通过数组 每一个元素的id,生成一个对象
//第一种方式
// let obj = {}
// arr.forEach(item => {
//   if(! obj[item.id]) {
//     obj[item.id] = item;
//   }
// })
//第二种方式 推荐
let obj = {}// 必须通过arr动态生成 对象, 否在 生成的对象变化,不会影响arr里面对象
 obj = arr.reduce((pre,cur) => {
  if(! pre[cur.id]) {
      pre[cur.id] = cur;
      return pre;
  }
}, obj)



arr.forEach(item => {
  obj[item.id].children ? obj[item.id].children.push(1) : obj[item.id].children = [] 
})
console.log(obj,arr)

注意:这里obj必须通过arr动态生成 对象, 否在 生成的对象变化,不会影响arr里面对象(引用类型);这样才能让我们数组里面的对象都会进行改变
结果显示:

P0T9F`G}2$RM6U}(NYLW68K.png

  • 非正常使用
let arr = [
{
    id:1,
    name:"zs"
  },
  {
    id:2,
    name: "ls"
  }
]
//不通过arr生成obj
//这是我们自定义的对象
let obj = {
  1: {
    id: 1,
    name: "zs"
  },
  2: {
    id: 2,
    name: "ls"
  }
}

arr.forEach(item => {
  obj[item.id].children ? obj[item.id].children.push(1) : obj[item.id].children = [] 
})
console.log(obj,arr)

结果显示:


I[{)J@KBPO7`$LGERUPT]_J.png

注意: 从结果显示我们,我们的自定义的对象 变化,但是对应的数组里的对象,没有变化的; 导致我们想改变数组的数据结构实现不了

  • 线性结构 => 树形结构(业务场景:菜单,实体类分类(部门,药品,..等),)
let array = [
  {
    id: 1,
    parent_id: 0,
    name: "四川省"
  },
  {
    id: 2,
    parent_id: 0,
    name: "广东省"
  },
  {
    id: 3,
    parent_id: 0,
    name: "江西省"
  },
  {
    id: 5,
    parent_id: 1,
    name: "成都市"
  },
  {
    id: 6,
    parent_id: 5,
    name: "锦江区"
  },
  {
    id: 7,
    parent_id: 6,
    name: "九眼桥"
  },
  {
    id: 8,
    parent_id: 6,
    name: "兰桂坊"
  },
  {
    id: 9,
    parent_id: 2,
    name: "东莞市"
  },
  {
    id: 10,
    parent_id: 9,
    name: "长安镇"
  },
  {
    id: 11,
    parent_id: 3,
    name: "南昌市"
  }
]

function listToTree(list) {

  let map = {};
  //
  list.forEach(item => {
    if (! map[item.id]) {

      map[item.id] = item;
    }
  });
  console.log(map)
  console.log(list)
  list.forEach(item => {
    if (item.parent_id !== 0) {
      map[item.parent_id].children ? map[item.parent_id].children.push(item) : map[item.parent_id].children = [item];
    }
  });
  console.log(list)
  return list.filter(item => {
    if (item.parent_id === 0) {
      return item;
    }
  })
}
console.log(listToTree(array));

  • 进一步的封装完善
//list: 后台返回的数据 ; options: 需要初始化的属性参数
function listToTree(list, otpions) {
  // 属性初始化
  // name: 表示原数据的从后台返回的字段名称,name2:表示前端组件需要的字段名称
  let {id = "id", parentId = "parentId", name = "name", name2 = "label" } = options;
  let map = {}
  map = arr.reduce((pre,cur) => {
    if(! pre[cur.id]) {
      //初始化自定义显示属性(因为有些组件需要传入的字段 label...等)
        pre[name2] = cur.name;
        pre[cur.id] = cur;
        return pre;
    }
  }, map)
  list.forEach(item => {
    if (item.parentId !== 0) {
      map[item.parentId].children ? map[item.parentId].children.push(item) : map[item.parentId].children = [item];
    }
  });
  return list.filter(item => {
    if (item.parentId === 0) {
      return item;
    }
  })
}
  • 真实业务场景使用 vue-treeselect,element-ui;效果图如下


    GGVZ5D910NOGJXA70~RG`ZC.png

    YHOM6WO27Z0LTL8JUOX49SX.png

核心sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.AppMedicineMapper">

    <!--resultMap 目的就是查询后的数据 进行赋值映射,如果没有就是null-->
    <resultMap type="com.ruoyi.system.domain.AppMedicine" id="AppMedicineResult">
        <result property="id" column="id"/>
        <result property="medicineId" column="medicine_id"/>
        <result property="name" column="name"/>
        <result property="type" column="type"/>
        <result property="picture" column="picture"/>
        <result property="attention" column="attention"/>
        <result property="disable" column="disable"/>
        <result property="des" column="des"/>
        <result property="function" column="function"/>
        <result property="diseaseId" column="disease_id"/>
        <result property="medicinetypeId" column="medicinetype_id"/>
        <result property="delFlag" column="del_flag"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <association property="appMedicineType" column="medicinetype_id" javaType="AppMedicineType" resultMap="medicineType" />
    </resultMap>
    <resultMap id="medicineType" type="AppMedicineType">
        <!--必须把关联的字段 不能和主表字段区别-->
        <id property="id" column="type_id"></id>
        <result property="name" column="type_name"></result>
    </resultMap>

    <!--查询药品,关联药品分类,-->
    <select id="selectMedicineList" parameterType="AppMedicine" resultMap="AppMedicineResult">
        select t1.id,t1.medicine_id,t1.name, t1.picture, t1.attention,t1.`disable`,t1.des,t1.`function`,t1.disease_id,t1.medicinetype_id,
        t1.del_flag,t1.create_by,t1.create_time,t1.update_by,t1.update_time,
        t2.id as type_id, t2.name as type_name
        from app_medicine t1
        left join app_medicine_type t2 on t1.medicinetype_id = t2.id
        where t1.del_flag = "0"
        <if test="name != null and name != ''">
            and t1.name like concat("%", #{name}, "%")
        </if>
     </select>


</mapper>

核心template

 <el-table v-loading="loading" :data="AppMedicineList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="药品id" align="center" prop="id" v-if="false"/>
      <el-table-column label="药品名称" align="center" prop="name" />
      <el-table-column label="分类名称" align="center" prop="appMedicineType.name" />
      <el-table-column label="药品图片" align="center" prop="picture" class-name="myImg" >
           <template slot-scope="scope">
          <img :src="scope.row.picture" alt="" style="width:40px;height:40px" />
        </template>
      </el-table-column>
      <el-table-column show-overflow-tooltip label="注意事项" align="center" prop="attention" />
      <el-table-column show-overflow-tooltip label="药品忌" align="center" prop="disable" />
      <el-table-column show-overflow-tooltip label="药品描述" align="center" prop="des" />
      <el-table-column show-overflow-tooltip label="药品功效" align="center" prop="function" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['system:AppMedicine:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['system:AppMedicine:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>

对象 => 数组

  • 常用的操作
 let obj = {
        id: "001",
        name: "zs",
        age: 10
    }
    Object.keys(obj).forEach(item => {
        console.log(item)
    })
  • 我们为什么要 对象转换成数组? 方便业务场景需要,因为不管遍历,还是渲染,数组方便对数据 变形(分组,排序,合并,交叉,非交叉,统计)
    敬请期待
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容