jqgrid获取原始数据,js对象拷贝

用vue做项目碰到的一个js中关于对象拷贝的问题

1.jqGrid获取行数据不能获取原始json数据的问题.

jqGrid的$(your tableId).jqGrid(“getRowData”,id);方法是获取对应行id的行数据的,这就有个问题了,若返回数据的list是这样的:

[
{
sex: 1,
score: {chinese: 100, math: 100},
hobby: [ball, tv, computor]
},
{
sex: 2,
score: {chinese: 50, math: 50},
hobby: [swim, run, read]
}
]

由于我们渲染列表时一些值会formatter,比如1代表男,2代表女,这样会导致我们使用jqGrid的getRowData获取一行数据时不能获取原始数据.(这里我的需求就是要求原始的数据).因此我在jqGrid的配置中加上了这个配置:

// 这是我用来记录原始数据的
var originalData;
// 这是初始化表格的方法
      initTable(){
      ...
      loadComplete: function (res) {
      // res是服务器返回的数据
            originalData = res.list;
        }
      }

然后我自己写了个通用的获取当前选中行(checkbox)的数据的方法
这里的拷贝对象是我的重点,后面细讲

function getSingleRowData(tableId) {
    // 行id
    var rowId = jQuery("#" + tableId).jqGrid('getGridParam','selarrrow');
    if(rowId.length == 0){
        layer.msg("你没有选择任何行");
        return null;
    }
    if(rowId.length > 1){
        layer.msg("你只能选择一行");
        return null;
    }
    // 取的是原始json行数据(通过遍历数据后比较选中行id与原始数据的id来获取原始数据)
    for(var i = 0; i < originalData.length; i++){
        if(originalData[i].id == rowId[0]){
            // 拷贝对象(不能让后续vue使用的对象跟原始json中的对象有相同的引用)
            // *********第一种拷贝对象的方法 ************
            // var proto = Object.getPrototypeOf(originalData[i]);
            // return Object.assign({},Object.create(proto),originalData[i]);
            // **********第二种拷贝对象的方法************
            return JSON.parse(JSON.stringify(originalData[i]))
        }
    }
}

关于拷贝对象,我自己试验了3种方法.
为什么要用拷贝对象?
在后面我使用的vue,大概情况是这样:

  • 页面中input使用v-model与vue的data中的我的对象绑定起来,类似这样:
<div class="form-group">
                                    <label class="col-md-3 control-label">名称</label>
                                    <div class="col-md-9">
                                        <input type="text" class="form-control" placeholder="名称" v-model="obj.slName">
                                    </div>
                                </div>
                                <div class="form-group" v-if="obj.slCode != null">
                                    <label class="col-md-3 control-label">编码</label>
                                    <div class="col-md-9">
                                        <input type="text" class="form-control" placeholder="编码" v-model="obj.slCode" readonly>
                                    </div>
                                </div>
  • 我编辑的时候会调用我的getSingleRowData方法把当前选中行的数据赋值给vue中的data:
var vm = new Vue({
    el: "#app",
    data(){
        return {
            obj: {id:null, slName:null, remark:null, srId:null, storageId:null, slt:null, disabledState:true, slCode:null}
        }
    },
    methods:{
        edit(){
            // 获取选择的data
            var data = getSingleRowData("jqGrid");
            if (data == null) {
                return;
            }
            // 赋值
            this.obj = data;
        },

这样就会导致一个问题,当我编辑时,修改了一个值,但我没保存,而是取消了修改,但这是vue中的obj对象的属性已经改变,由于我的原始数据跟vue对象是同一个引用,导致我的原始数据也改变,当我再次点击编辑时,这时的数据是错误的,并不是该对象原本的数据,而是我上次点击编辑后没保存的数据(由于我的编辑是没有到后台取数据的,而是直接取的表格中的那一行数据).所以会用到拷贝对象

拷贝对象

三种方法(我试验过的)

1.
很简单,原理是先转json字符串在转对象

JSON.parse(JSON.stringify(obj))

2.
自己写一个,原理是遍历对象,把key和value追加到新对象里,如果value也是一个对象,在递归调用(这里还牵涉到js的深度拷贝和浅拷贝,如果在value是一个对象的情况下不继续递归的话,那这个value也是可以影响原对象的属性的,可以搜一搜).

function copyObj(obj) {
    // 新对象
    var o = new Object();
    // 遍历
    for(var i in obj){
    // 如果属性是object类型,则递归调用
        if(typeof obj[i] == 'object'){
            var temp = copyObj(obj[i]);
            // 递归调用后的返回值追加到新对象中
            o[i] = temp;
        } else {
        // 否则追加到新对象中
            o[i] = obj[i];
        }
    }
    return o;
}

3.
es6中的写法,用了一下,可以使用。。

 var proto = Object.getPrototypeOf(obj);
 var newObj = Object.assign({},Object.create(proto),obj);

最后,问题解决,在我修改vue中的obj时,我的原始对象并不会改变了.

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页