根据问题的答案,什么会影响Vue计算的属性是否会重新计算?我知道
Vue无法检测到对数组的以下更改:
当您使用索引直接设置项目时,例如。vm.items[indexOfItem]=newValue当您修改数组,例如vm.items.length=newLength
这里肯定是另一种情况,因为我显式地将新值分配给数组。
目标
- 图像滑块必须显示当前选定的照片
- 当
photosURLs
数组为空时,滑块应该显示伪图像(如"无图像"( - 当
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);