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