问题:笔者做项目的时候发现有时候会发现带有__ob__: Observer
数组后缀的就是没有办法取到值,但是 console.log
却能看得到值
项目片段中的打印
console.log('============');
console.log('arr', arr, arr.length);
console.log('=============');
打印效果如下
那么首先先解释一下vue取值的方式是Ajax异步的,换句人话就是说,你还没有从数据库中取到值放到对应的数组中去你那边就开始取值,那肯定是取不到的,所以我们可以有两种方法,第一种把这个换成同步的形式等你加载完之后再进行取值,或者说采用第二种方式就是设一个延迟等去取完之后呢你在进行赋值即可!那么你就可以看到这个值了,这也是最简单的方法(弊端在于不知道数据什么时候处理好),完美的方法请看方案二
方案一
mounted() {
setTimeout(()=>{
//代码
},800)
}
那么再什么时候数组后面会出现ob: Observer ,这个后缀其实是Vue监控变量产生的,如果你是使用 push添加的对象信息就会出现ob: Observer,引用了一个对象的时候引用值也会产生ob,例如this.datalist = arr,父组件传给子组件等引用了一个对象,均会出现ob ,但是取不到值只有异步出现的ob会取不到值。
方案二思考:
什么时候数据回来,那么把所有异步操作都变为同步,就能保证数据能准时拿到了,但是我们处理数据往往会用到循环,那么就选用同步循环了,接口数据就用aswnc 与 await了
for循环是异步的,说明如下:
控制台实验一番即可验证结果
let arr = [1,2,3]
function A() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(4)
},10)
})
}
arr.forEach(async item=>{
console.log(item)
if(item===2){
console.log(await A())
}
})//1234
forEach是同步的,说明如下:
控制台实验一番即可验证结果:
let arr = [1,2,3]
function A() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(4)
},10)
})
}
async function B() {
for(let i=0;i<arr.length;i++){
let item = arr[i];
console.log(item)
if(item===2){
console.log(await A())
}
}
}
B()//1243
方案二:
所以我们把操作全部转为同步代码即可保证经过一段代码数据处理完了,forEach循环改为同步循环for,就会避免异步监听产生的__ob__
了,而涉及计到引用产生__ob__
,有如下方案:
1.对象可以使用Object.assign({},obj)
去掉复杂类型的引用产生的__ob__
2.数组嵌套对象可以使用:JSON.parse(JSON.stringify(arr))去掉引用产生的__ob__
3.复杂嵌套可以使用如下功能函数深拷贝
function clone(target, map = new Map()) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
cloneTarget[key] = clone(target[key], map);
}
return cloneTarget;
} else {
return target;
}
};
到此为止就完美的解决问题了,nice,只要保证处理数据是同步就没有任何问题了
附上解决前的跟解决后的对比
解决后:
参考文献:https://blog.csdn.net/wanshuai12138/article/details/124809122
https://blog.csdn.net/wanshuai12138/article/details/124809122