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時,我的原始對象並不會改變了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章