Vue项目中遇到的对象数据获取问题
浏览器打印数据即获取异常问题
在项目中,大致代码大概如下:
1、初始化对象:
getCategory().then(res=>{
// 1.获取分类数据
this.categories=res.data.category.list
// 2.初始化每个类别的子数据
for (let i=0;i<this.categories.length;i++){
this.categoryData[i]={
subcategories:{},
categoryDetail:{
'pop':[],
'new':[],
'sell':[]
}
}
}
// 3.请求第一个分类的数据
this._getSubcategories(0)
2、向对象中添加数据:
getSubcategory(mailKey).then(res=>{
this.categoryData[index].subcategories=res.data
this.categoryData={...this.categoryData}
this._getCategoryDetail(POP)
this._getCategoryDetail(SELL)
this._getCategoryDetail(NEW)
})
_getCategoryDetail(type){
// 获取请求的minWallKey
const minWallkey=this.categories[this.currentIndex].miniWallkey
// 发送请求
getCategoryDetail(minWallkey,type).then(res=>{
// 3.将获取的数据保存下来
this.categoryData[this.currentIndex].categoryDetail[type]=res
this.categoryData={...this.categoryData}
})
}
对于上述添加数据中存在疑惑的地方:即为什么this.categoryData[this.currentIndex].categoryDetail[type]=res中已经改变对象的值,还要采用this.categoryData={...this.categoryData}再进行一次赋值
如果不再进行一次赋值,则在computed中则出现无法获取对象中的数据的错误【即在如下代码中,console.log(this.categoryData), console.log(this.categoryData[this.currentIndex])
中均获取完整数据,而console.log(this.categoryData[this.currentIndex].subcategories)获取数据为空】:
computed:{
showSubcategory() {
if (this.currentIndex===-1) return {}
// console.log(this.categoryData[this.currentIndex])
console.log(this.categoryData)
console.log(this.categoryData[this.currentIndex])
console.log(this.categoryData[this.currentIndex].subcategories)
return this.categoryData[this.currentIndex].subcategories
},
showCategoryDetail() {
if (this.currentIndex===-1) return []
return this.categoryData[this.currentIndex].categoryDetail[this.currentType]
}
},
浏览器打印结果如下【因为异步原因,所以初始时subcategories值为空】所示:
原因如下所示:
一、获取数据为空问题
浏览器打印问题,这是console在浏览器的一个问题,简单来说就是chrome在console输出时还是原样,但是展开时却是获取数据后的状态。【如果想要显示当时的信息可以用JSON.stringify(obj)把对象处理成JSON进行输出,就可以看到初始和修改后的】
例子如下所示【JSON例子不做阐述】:
window.onload=function (){
var obj={
a:123,
b:[1,2,3],
c:{
name:'',
age:0
}
}
console.log(obj)
console.log(obj.b[0])
console.log(obj.c.age)
obj.a=333
obj.b[0]=1111
obj.c.name='Alice'
obj.c.age=10
}
在该例子中浏览器的打印如下所示:
在打印出来的结果中可以看出,console.log(obj)输出的数组属性和对象属性的值均为修改后的,但是console.log(obj.b[0])和console.log(obj.c.age)获取到的值均为修改前的。【后面发现,浏览器暂停时获取数据准确,一段时间后获取的获取到了异步数据,当我们查看时已经获取到了数据,从而造成一开始查看即是获取到数据后的数组】
由此可以解释项目中的console.log(this.categoryData[this.currentIndex].subcategories)获取数据为空得问题。
二、为什么要采用拓展运算符进行再次赋值
采用拓展运算符进行再次赋值是为了及时改变computed中的showCategoryDetail()和showSubcategory()中获取的值并反馈。
解析如下:
因为计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的。
其透露信息如下所示:
computed
会搜集并记录依赖。- 依赖发生了变化才会重新计算
computed
,由于computed
是有缓存的,所以当依赖变化之后,第一次访问computed
属性的时候,才会计算新的值。 - 只能搜集到响应式属性依赖,无法搜集到非响应式属性依赖。
- 无法搜集到当前
vm
实例之外的属性依赖。
对于项目中的响应式实现:
1、向响应式的数组或者对象中修改已有的属性的方法,对于在data中声明了的基本数据类型而言,一般都是响应式的。但是对于数组和对象而言,不一定是响应式的。
【原因:Object.defineProperty虽然实现是双向绑定,但是只能对对象的属性进行劫持,会深度遍历整个对象,不管层级多深。但是只要数组中嵌套了对象,就只能监听到对象的数据变化,无法监听到数组的变化,因而出现响应式问题】
data(){
return{
categories:[],
categoryData:{},
currentIndex:-1,
}
},
2、如果在data声明时对象、数组就带有的属性,后面改变的时候会触发响应式。但如果是如项目中所示,在后面的代码中添加的初始化对象、数组属性,当该属性发生变化时,该对象/数组不会实现响应式。
getCategory().then(res=>{
// 1.获取分类数据
this.categories=res.data.category.list
// 2.初始化每个类别的子数据
for (let i=0;i<this.categories.length;i++){
this.categoryData[i]={
subcategories:{},
categoryDetail:{
'pop':[],
'new':[],
'sell':[]
}
}
}
// 3.请求第一个分类的数据
this._getSubcategories(0)
3、要使不在data中生命的对象属性或者数组实现响应式,则需要对这个对象/数组进行整体的替换,使其保持响应式。
向响应式的数组和对象替换为新的响应式数据可以采用扩展运算符、或直接进行复制。因为data中声明的数据已经添加了访问器属性setter,当重新赋值一个堆内存地址时,该数组或者对象也会循环遍历添加访问器属性,从而实现响应式。当向响应式的数组或者对象中新增一个响应式的属性可以使用方法this.$set()或者数组变异方法。
getSubcategory(mailKey).then(res=>{
this.categoryData[index].subcategories=res.data
this.categoryData={...this.categoryData}
this._getCategoryDetail(POP)
this._getCategoryDetail(SELL)
this._getCategoryDetail(NEW)
})
_getCategoryDetail(type){
// 获取请求的minWallKey
const minWallkey=this.categories[this.currentIndex].miniWallkey
// 发送请求
getCategoryDetail(minWallkey,type).then(res=>{
// 3.将获取的数据保存下来
this.categoryData[this.currentIndex].categoryDetail[type]=res
this.categoryData={...this.categoryData}
})
}
【文中查阅了一部分网上资料,并进行使用】
更多推荐
所有评论(0)