实现Lodash.set 、根据antd的Form.Item组件中的NamePath给对象目标位置赋值

 一、适用范围

传递NamePath,根据NamePath给对象的目标位置赋值,且不会影响对象中其它属性。

模拟:lodash.set | Lodash 中文文档

关于NamePath:antd组件库中的Form.Item属性,可以输入NamePath,会自动填充至对象的目标位置

场景:比如一个对象 obj , 想给对象目标位置赋值,如果你知道这个路径是固定的,那当然可以直接通过点语法 obj.a.b 一步步赋值,但是当需要赋值的路径是动态生成的时候,就不能通过点语法了,需要根据用户传入的路径来进行动态赋值,比如一会想给 obj.a.b赋值,一会想给 obj.c.d[2].e赋值。

二、使用示例

 

 三、代码及原理

原理已经在下方注释中写的很详细了,主要是利用数组的reduce迭代方法,把指针一步步迭代到目标位置,然后赋值

当path中的路径在obj中存在时,将会直接沿着这条线往下走,当路径不存在时,将会生成新的对象或数组,再继续走下去

/**
 * 根据NamePath,将对象中指定位置的值赋值
 * @param {object} obj 要被操作的对象
 * @param {(string | number)[] | string} path 路径数组
 * @param {*} value 要赋值的数据
 * @returns {object} 返回修改后的对象
 */
const setObjByNamePath = (obj, path, value) => {
    if (Object(obj) !== obj) return obj; // 当传入的obj不是对象时
    // 如果path不是数组,则从字符串路径转数组
    if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
    //迭代path,在obj上沿着path一步步往下,找到目标位置,targetPoint是迭代后,目标位置的上一级指针
    let targetPoint = path.slice(0, -1).reduce((lastObj, nowKey, i) => {//slice(0, -1)去掉了最后一个,迭代除最后一个以外的所有内容,每次都返回一个对象/数组的指针给下一个元素调用
        return Object(lastObj[nowKey]) === lastObj[nowKey] // Object(lastObj[nowKey])构造这个键值的对象,如果和原本的不一样说明key不存在
            ? lastObj[nowKey]// 是的话,key存在,那么就把当前的对象继续传递下去
            // 不存在的话,就需要创建这个key,下面判断要新建的是对象还是数组
            : lastObj[nowKey] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] //下一个键是数组索引(数字)的话   注:>> 0是转数字,如果不是纯数字就会变成0, +path[i + 1]也是转数字,但是不是纯数字也可以转
                ? [] //是的话,就新建一个数组,防止下面使用索引报错
                : {}// 否的话,就新建一个对象
    }, obj);//这里的obj是初始值(初始的顶层对象)
    //到最后,把值分配
    targetPoint[path[path.length - 1]] = value; //最后将值分配给最后一个键 
    return obj; //返回修改后的对象的地址,有可能有人操作会用到
};

//测试用例 1   //指定的路径存在时,会直接赋值
let testObj = {
    a:{
        b: []
    },
    ccc: 2
}
setObjByNamePath(testObj , ["a","b", 2] , 666) //在testObj.a.b[2]的位置赋值666
console.log(testObj) 


//测试用例 2   //指定的路径不存在时,会创建这个路径
let testObj2 = {}
setObjByNamePath(testObj2 , ["a",1, "b"] , 777) //在testObj2.a[1].b的位置赋值777
console.log(testObj2) 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
antd Form.List ,一个 Form.Item 可以通过使用 getFieldDecorator 方法来获取自身的值,而获取其他 Form.Item 的值则需要通过 Form.List 的方法进行。例如,可以通过调用 form.getFieldValue 方法来获取其他 Form.Item 的值。具体实现步骤如下: 1. 在 Form.List ,给每个 Form.Item 一个唯一的 name 属性,例如 name={`items[${index}].name`},其 index 为当前 Form.Item 的索引。 2. 在 getFieldDecorator 方法,使用 getFieldValue 方法来获取其他 Form.Item 的值。示例代码如下: ```jsx {getFieldDecorator(`items[${index}].name`, { initialValue: item.name, rules: [{ required: true, message: 'Please input name' }], })( <Input placeholder="Enter name" /> )} {getFieldDecorator(`items[${index}].age`, { initialValue: item.age, rules: [{ required: true, message: 'Please input age' }], })( <InputNumber placeholder="Enter age" min={0} /> )} {getFieldDecorator(`items[${index}].email`, { initialValue: item.email, rules: [{ required: true, message: 'Please input email' }], })( <Input placeholder="Enter email" /> )} ``` 3. 在需要获取其他 Form.Item 值的地方,调用 form.getFieldValue 方法。示例代码如下: ```jsx const handleSubmit = e => { e.preventDefault(); form.validateFields((err, values) => { if (!err) { // 获取其他 Form.Item 值 const names = form.getFieldValue('items').map(item => item.name); console.log(names); // 提交表单 console.log('Received values of form: ', values); } }); }; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值