saleExplain.wxarticleTitle = matchedArticle.name
if (matchedArticle) {
wxarticleTitle = matchedArticle.name;
}
}
return {
...saleExplain,
wxarticleTitle
};
比之下,第二个代码片段直接修改了原始的 saleExplain 对象,将 wxarticleTitle 属性赋值给它。虽然这样可以实现相同的功能
不可变性(Immutability)是指对象在被创建后,其状态(即属性值)不能被改变的特性。换句话说,一旦对象被创建,它的内容就无法被修改。如果需要改变对象的状态,必须创建一个新的对象,而不是修改现有的对象。
对比:两种设置 Vue 对象属性的方法
在 Vue 开发中,处理对象属性的更新时,有两种常见的方法:直接修改对象属性和使用不可变性原则。下面我们通过一个具体的示例来对比这两种方法的原理和效果。
示例代码对比
方法一:使用不可变性原则
async loadSaleExplains() {
try {
const saleExplains = await Spu.getSaleExplainsBySpuId(this.spuId);
console.log(saleExplains);
// 获取所有微信文章
const allWxArticles = await wxarticle.getWxarticleList(0, 0, 0);
// 为每个 saleExplain 设置 wxarticleTitle
this.saleExplains = saleExplains.map(saleExplain => {
let wxarticleTitle = '';
if (saleExplain.wxarticle_id) {
const matchedArticle = allWxArticles.items.find(article => article.id === saleExplain.wxarticle_id);
if (matchedArticle) {
wxarticleTitle = matchedArticle.name;
}
}
return {
...saleExplain,
wxarticleTitle
};
});
} catch (error) {
if (error.code === 10020) {
this.$message.info('该spu暂无销售说明,请先添加');
} else {
this.$message.error('加载销售说明失败,请重试');
}
console.error(error);
}
}
方法二:直接修改对象属性
async loadSaleExplains() {
try {
this.saleExplains = await Spu.getSaleExplainsBySpuId(this.spuId);
console.log(this.saleExplains)
// 获取所有微信文章
const allWxArticles = await wxarticle.getWxarticleList(0, 0, 0)
// 为每个 saleExplain 设置 wxarticleTitle
this.saleExplains.forEach(saleExplain => {
if (saleExplain.wxarticle_id) {
const matchedArticle = allWxArticles.items.find(article => article.id === saleExplain.wxarticle_id)
if (matchedArticle) {
saleExplain.wxarticleTitle = matchedArticle.name
}
}
})
} catch (error) {
if (error.code === 10020) {
this.$message.info('该spu暂无销售说明,请先添加')
} else {
this.$message.error('加载销售说明失败,请重试')
}
console.error(error)
}
}
不可变性原则的优势
-
保持数据不可变性:
- 在第一个代码片段中,通过
map
方法创建一个新数组,并返回一个新的对象,而不是直接修改原始对象。这样做确保了数据的不可变性。 - 不可变性有助于避免意外的副作用,使代码更容易理解和维护。
- 在第一个代码片段中,通过
-
更清晰的数据流:
- 创建新的对象可以清楚地看到数据的变化过程,每个阶段的数据都是独立的,不会影响之前的数据。
- 这使得代码逻辑更加透明和可追踪。
-
更好的性能:
- 在比较对象是否相等时,不可变对象可以通过比较引用来实现,而不需要递归地比较每个属性,这可能带来性能上的优势。
-
Vue 响应式系统的正确工作:
- 在 Vue 中,响应式系统依赖于对象的 getter 和 setter。当对象属性在初始化时定义好,Vue 可以正确地跟踪和响应属性的变化。
直接修改对象属性的劣势
-
违背不可变性原则:
- 在第二个代码片段中,直接修改了原始对象的属性,这违背了不可变性的原则,可能会导致意外的副作用。
-
Vue 响应式系统的局限:
- 当通过直接赋值的方式为对象动态添加新属性时,Vue 无法自动为这些新属性创建 getter 和 setter。
- 结果是,Vue 无法检测到这些属性的变化,导致视图无法更新。例如,当在 input 中删除
wxarticleTitle
的值时,Vue 无法检测到变化,导致视图没有更新。
解决方法
为了让 Vue 正确地跟踪和响应对象属性的变化,可以使用 Vue.set()
方法显式地添加新属性:
this.$set(saleExplain, 'wxarticleTitle', matchedArticle.name);
或者使用计算属性来获取 wxarticleTitle
的值,这样可以避免直接修改对象,并且计算属性会自动跟踪其依赖项的变化并触发更新。
总结
在 Vue 开发中,遵循不可变性原则和使用 Vue 提供的响应式方法,可以确保数据流的清晰性和代码的可维护性。通过对比上述两种方法,我们可以看到不可变性原则的优势,以及直接修改对象属性的潜在问题。为了确保 Vue 的响应式系统能够正常工作,建议尽量使用不可变性原则和 Vue 提供的方法来管理对象属性。