Vue计算属性尚未更新,尽管它所依赖的数组已显式重新分配



根据问题的答案,什么会影响Vue计算的属性是否会重新计算?我知道

Vue无法检测到对数组的以下更改:

当您使用索引直接设置项目时,例如。vm.items[indexOfItem]=newValue当您修改数组,例如vm.items.length=newLength

这里肯定是另一种情况,因为我显式地将新值分配给数组

目标

  1. 图像滑块必须显示当前选定的照片
  2. photosURLs数组为空时,滑块应该显示伪图像(如"无图像"(
  3. product.photosURLs更新时,滑块必须显示更新的照片(如果所有照片都已删除,则显示伪照片(

实施

下面的实施达到了第一个和第二个目标。

标记(pug(

.ImageSliderForNarrowScreens
.ImageSliderForNarrowScreens-ActiveImage-DefaultBackgroundUnderlay
.ImageSliderForNarrowScreens-ActiveImage-ImageLayer(
v-if="product.photosURLs.length < 2"
:style="`background-image: url(${activeProductPhotoURL_ForImagesViewer});`"
)
template(v-else)
.ImageSliderForNarrowScreens-ActiveImage-ImageLayer(
:key="'IMAGE_SLIDER-IMAGE-'+activeProductPhotoArrayIndexForImagesViewer"
:style="`background-image: url(${activeProductPhotoURL_ForImagesViewer});`"
v-touch:swipe.left="switchImagesSliderToPreviousPhoto"
v-touch:swipe.right="switchImagesSliderToNextPhoto"
)

逻辑(TypeScript(

图像滑块指product.photosURLs

  • 当用户切换到编辑模式时,product.photosURLs将被复制到uploadedProductPhotosURLs,即更新但尚未提交的照片URL的数组
  • uploadedProductPhotosURLs将被提交时,uploadedProductPhotosURLs将被复制到product.photosURLs
import { Vue, Component, Watch } from "vue-property-decorator";

@Component
export default class MyComponent extends Vue {
private product!: Product;
private uploadedProductPhotosURLs: Array<string> = [];
/* --- Product photos viewing ------------------------------------------------------------------------------------ */
private activeProductPhotoArrayIndexForImagesViewer: number = 0;
private get activeProductPhotoURL_ForImagesViewer(): string {
if (this.product.photosURLs.length === 0) {
return PRODUCT_DUMMY_PHOTO_URL;
}
return this.product.photosURLs[this.activeProductPhotoArrayIndexForImagesViewer];
}
// --- Well, it does not matter, I just mentioned it in template
private switchImagesViewersToNextProductPhoto(): void {
this.activeProductPhotoArrayIndexForImagesViewer =
this.activeProductPhotoArrayIndexForImagesViewer !== this.product.photosURLs.length - 1 ?
this.activeProductPhotoArrayIndexForImagesViewer + 1 : 0;
}
private switchImagesViewersToPreviousProductPhoto(): void {
this.activeProductPhotoArrayIndexForImagesViewer =
this.activeProductPhotoArrayIndexForImagesViewer !== 0 ?
this.activeProductPhotoArrayIndexForImagesViewer - 1 : this.product.photosURLs.length - 1;
}
// ------------------------------------------------------------

/* --- Submitting of changes ------------------------------------------------------------------------------------ */
private async onClickSaveProductButton(): Promise<void> {
try {
await ProductsUpdatingAPI.submit({
// ...
productPhotosURLs: this.uploadedProductPhotosURLs
});

console.log("checkpoint");
console.log("uploadedProductPhotosURLs:");
console.log(this.uploadedProductPhotosURLs);
console.log("'product.photosURLs' before updating:");
console.log(JSON.stringify(this.product.photosURLs, null, 2));
this.product.photosURLs = this.uploadedProductPhotosURLs;
// normally, I must set it to 0, but for now it does not affect
// this.activeProductPhotoArrayIndexForImagesViewer = 0;
console.log("'product.photosURLs' after updating:");
console.log(JSON.stringify(this.product.photosURLs, null, 2));
} catch (error) {
// ....
}
}
}

问题

this.product.photosURLs为空时,让我们尝试添加并提交新照片。调试输出为:

checkpoint
uploadedProductPhotosURLs:
[
"https://XXX/c732d006-1261-403a-a32f-f73c0f205aa8.jpeg", 
"https://XXX/2b7ae2e2-4424-4038-acee-9624d5b937bc.jpeg", 
__ob__: Observer
]
'product.photosURLs' before updating:
[]
'product.photosURLs' after updating:
[
"https://XXX/c732d006-1261-403a-a32f-f73c0f205aa8.jpeg",
"https://XXX/2b7ae2e2-4424-4038-acee-9624d5b937bc.jpeg"
]

从算法的角度来看,所有正确但计算的属性activeProductPhotoURL_ForImagesViewer(TypeScript OOP语法中的getter(都没有重新计算!这意味着PRODUCT_DUMMY_PHOTO_URL仍在显示。

private get activeProductPhotoURL_ForImagesViewer(): string {
if (this.product.photosURLs.length === 0) {
return PRODUCT_DUMMY_PHOTO_URL;
}
return this.product.photosURLs[this.activeProductPhotoArrayIndexForImagesViewer];
}

如果要删除图像,则相同:调试输出与预期匹配,但已删除的缓存图像仍在显示!

checkpoint
uploadedProductPhotosURLs:
[__ob__: Observer]
'product.photosURLs' before updating:
[
"https://XXX/c732d006-1261-403a-a32f-f73c0f205aa8.jpeg",
"https://XXX/2b7ae2e2-4424-4038-acee-9624d5b937bc.jpeg"
]
'product.photosURLs' after updating:
[]

如果要替换图像,则相同。

扩展@Estradiaz的评论,正如Vue自己的文档中所提到的:深度反应性,

Vue无法检测属性添加或删除。

您可能需要使用空数组初始化product.photosURLs,或者您需要使用Vue.set()onClickSaveProductButton函数中为this.product.photosURLs赋值,如下所示:

Vue.set(this.product, 'photosURLs', this.uploadedProductPhotosURLs);

最新更新