const themeBehavior = Behavior({
behaviors: [],
properties: {
theme: Object,
},
/**
* 组件的初始数据
*/
data: {
spuList: Array,
topImg: String,
randoms: Array
},
observers: {
'theme': function (theme) {
console.log(theme)
if (!theme) {
return
}
this.setData({
spuList: theme.spu_list,
topImg: theme.internal_top_img,
descriptions: this.splitDescription(theme.description)
})
}
},
methods: {
onGoToSpu(event) {
const pid = event.currentTarget.dataset.spuId
wx.navigateTo({
url: `/pages/detail/detail?pid=${pid}`
})
},
splitDescription(description) {
if (!description) {
return []
}
console.log(description.split('#'))
return description.split('#');
}
}
})
export {
themeBehavior
}
// components/spu-list/index.js
import {themeBehavior} from "../behaviors/theme-beh";
Component({
behaviors: [themeBehavior],
properties: {},
data: {
empty: false,
loading: true,
loadingType: 'loading'
},
methods: {
onLoadImg(event) {
const {height, width} = event.detail
this.setData({
h: height,
w: width,
})
},
empty() {
wx.lin.showEmptyScreen({
text: '该分类暂时还没有商品'
})
},
onWaterFlowRender() {
wx.lin.renderWaterFlow(this.data.spuList, false, () => {
console.log('渲染成功')
})
}
},
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
this.onWaterFlowRender()
this.setData({
empty: false,
loadingType: 'end'
})
} else {
this.empty()
}
}
}
})
// components/spu-list/index.js
import {themeBehavior} from "../behaviors/theme-beh";
Component({
behaviors: [themeBehavior],
properties: {},
data: {
empty: false,
loading: true,
loadingType: 'loading',
formattedSpuList: []
},
methods: {
onLoadImg(event) {
const {height, width} = event.detail
this.setData({
h: height,
w: width,
})
},
empty() {
wx.lin.showEmptyScreen({
text: '该分类暂时还没有商品'
})
},
onWaterFlowRender() {
wx.lin.renderWaterFlow(this.data.formattedSpuList, false, () => {
console.log('渲染成功')
})
}
},
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
const formattedSpuList = [...spuList]
this.setData({
formattedSpuList: formattedSpuList,
empty: false,
loadingType: 'end'
}, () => {
this.onWaterFlowRender()
})
} else {
this.setData({
formattedSpuList: [],
empty: true,
loadingType: 'end'
})
}
}
}
})
对面上两个代码
第一个不可以运行
第二个可以运行
加一个中间变量formattedSpuList 转换新的就可以运行
很多时候赋值不上用一个新的变量就可以运行成功 大概率是
const themeBehavior = Behavior({
behaviors: [],
properties: {
theme: Object,
},
/**
* 组件的初始数据
*/
data: {
spuList: Array,
topImg: String,
randoms: Array
},
observers: {
'theme': function (theme) {
console.log(theme)
if (!theme) {
return
}
this.setData({
spuList: theme.spu_list,
topImg: theme.internal_top_img,
descriptions: this.splitDescription(theme.description)
})
}
},
methods: {
onGoToSpu(event) {
const pid = event.currentTarget.dataset.spuId
wx.navigateTo({
url: `/pages/detail/detail?pid=${pid}`
})
},
splitDescription(description) {
if (!description) {
return []
}
console.log(description.split('#'))
return description.split('#');
}
}
})
export {
themeBehavior
}
// components/spu-list/index.js
import {themeBehavior} from "../behaviors/theme-beh";
Component({
behaviors: [themeBehavior],
properties: {},
data: {
empty: false,
loading: true,
loadingType: 'loading'
},
methods: {
onLoadImg(event) {
const {height, width} = event.detail
this.setData({
h: height,
w: width,
})
},
empty() {
wx.lin.showEmptyScreen({
text: '该分类暂时还没有商品'
})
},
onWaterFlowRender() {
wx.lin.renderWaterFlow(this.data.spuList, false, () => {
console.log('渲染成功')
})
}
},
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
this.onWaterFlowRender()
this.setData({
empty: false,
loadingType: 'end'
})
} else {
this.empty()
}
}
}
})
// components/spu-list/index.js
import {themeBehavior} from "../behaviors/theme-beh";
Component({
behaviors: [themeBehavior],
properties: {},
data: {
empty: false,
loading: true,
loadingType: 'loading',
formattedSpuList: []
},
methods: {
onLoadImg(event) {
const {height, width} = event.detail
this.setData({
h: height,
w: width,
})
},
empty() {
wx.lin.showEmptyScreen({
text: '该分类暂时还没有商品'
})
},
onWaterFlowRender() {
wx.lin.renderWaterFlow(this.data.formattedSpuList, false, () => {
console.log('渲染成功')
})
}
},
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
const formattedSpuList = [...spuList]
this.setData({
formattedSpuList: formattedSpuList,
empty: false,
loadingType: 'end'
}, () => {
this.onWaterFlowRender()
})
} else {
this.setData({
formattedSpuList: [],
empty: true,
loadingType: 'end'
})
}
}
}
})
对面上两个代码
第一个不可以运行
第二个可以运行
加一个中间变量formattedSpuList 转换新的就可以运行
很多时候赋值不上用一个新的变量就可以运行成功 大概率是就能运行
在小程序开发中,有时会遇到数据绑定更新不及时或者无法触发的问题。这个现象通常与小程序的视图层和逻辑层之间的数据同步机制有关。以下是一些可能导致这种现象的原因和解决方法:
1. 数据绑定机制
小程序的 setData
方法用于将数据从逻辑层发送到视图层,并触发视图的更新。如果直接修改绑定的数据,有时可能不会触发视图更新,特别是在复杂的数据结构或较大的数据量时。
2. 异步渲染
小程序的 setData
是异步的,某些情况下直接修改数据可能不会立即反映在界面上。通过设置新的中间变量,可以确保数据变化被正确捕获和渲染。
3. 深拷贝与浅拷贝
在某些情况下,直接修改对象的属性可能不会触发视图更新。使用 JSON.parse(JSON.stringify(obj))
或 Object.assign({}, obj)
创建对象的深拷贝,确保数据变动被正确捕获。
4. 数据结构变化
小程序的视图层可能对数据结构的变化不敏感。通过设置新的变量,可以显式地通知视图层数据发生了变化。
具体分析你的代码
第一个版本
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
this.onWaterFlowRender()
this.setData({
empty: false,
loadingType: 'end'
})
} else {
this.empty()
}
}
}
这个版本中,spuList
直接被观察并用于触发渲染。然而,如果 spuList
的内容发生变化但引用不变,可能不会触发视图更新。
第二个版本
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
const formattedSpuList = [...spuList]
this.setData({
formattedSpuList: formattedSpuList,
empty: false,
loadingType: 'end'
}, () => {
this.onWaterFlowRender()
})
} else {
this.setData({
formattedSpuList: [],
empty: true,
loadingType: 'end'
})
}
}
}
在这个版本中,spuList
被复制到一个新的变量 formattedSpuList
。这种做法确保了数据变化被正确捕获和渲染。
总结
- 使用中间变量:通过创建新的变量,可以确保数据变化被正确捕获和渲染。
- 深拷贝:在必要时,使用深拷贝确保数据结构的变化被捕获。
- 确保数据引用变化:直接修改对象属性可能不会触发视图更新,确保引用发生变化。
通过这些方法,可以更好地控制数据绑定和视图更新,避免数据绑定更新不及时的问题。
在小程序开发中,数据绑定的更新机制有时可能不如预期般顺畅。为了更好地理解这一点,我们需要先理解 JavaScript 中的引用类型和浅拷贝、深拷贝的概念。
引用类型和引用变化
在 JavaScript 中,数组和对象是引用类型。当我们直接赋值或传递数组或对象时,实际上是传递它们的引用而不是实际的值。
例如:
let array1 = [1, 2, 3];
let array2 = array1;
array2.push(4);
console.log(array1); // [1, 2, 3, 4]
在这个例子中,array2
和 array1
引用的是同一个数组,所以对 array2
的修改会反映在 array1
上。
引用不变
当数据的引用不变时,小程序的 observers
或 setData
可能不会触发视图更新。
例如:
this.setData({
spuList: this.data.spuList
});
在这个例子中,spuList
的引用没有发生变化,即使内容发生了变化,小程序也可能不会触发视图的更新。
深拷贝和浅拷贝
为了确保视图更新,我们可以创建一个新引用。常用的方法有:
- 浅拷贝:
const newList = [...this.data.spuList];
- 深拷贝:
const newList = JSON.parse(JSON.stringify(this.data.spuList));
浅拷贝适用于一维数组或简单对象,而深拷贝适用于复杂的嵌套结构。
示例
假设我们有一个数组 spuList
,当内容发生变化时,我们希望视图能够更新:
// 原始数据
this.data.spuList = [1, 2, 3];
// 修改数据
this.data.spuList.push(4);
// 更新视图 - 引用不变,可能不会触发更新
this.setData({
spuList: this.data.spuList
});
// 创建新引用
const newList = [...this.data.spuList];
// 更新视图 - 引用改变,触发更新
this.setData({
spuList: newList
});
在这个示例中,newList
是 spuList
的一个新引用,因此 setData
会触发视图的更新。
你的代码中的应用
在你的第二个版本的代码中,通过创建 formattedSpuList
新的引用来确保视图更新:
observers: {
'spuList': function(spuList) {
if (spuList && spuList.length !== 0) {
const formattedSpuList = [...spuList];
this.setData({
formattedSpuList: formattedSpuList,
empty: false,
loadingType: 'end'
}, () => {
this.onWaterFlowRender();
});
} else {
this.setData({
formattedSpuList: [],
empty: true,
loadingType: 'end'
});
}
}
}
通过这种方式,即使 spuList
的内容发生了变化但引用不变,创建 formattedSpuList
的新引用确保了数据变化能够被捕获并触发视图更新。