Vue 3 使用计算对象获取图像信息,在模板中渲染该值后变成 NaN。

huangapple go评论53阅读模式
英文:

Vue 3 Using computed object to get image info works until I render the value in template, then becomes NaN

问题

以下是您要翻译的代码部分:

我有一个显示图像数组的应用程序在显示图像之前我需要根据图像的尺寸进行裁剪调整当我在一个vue子组件中加载图像时我使用一个计算函数箭头函数或常规函数),在浏览器的检查vue扩展中对象值都存在且正确但是当我尝试使用计算对象的参数时结果为零或NaN我使用了标准的计算函数和箭头计算函数两者的结果都相同

script setup>
import { computed } from 'vue';

const prop = defineProps({
    image: String,
    numberOfImages: {
        type: Number,
        default: 0,
    },
});

const getDimensions = computed(function () {
    get: {
        const newImg = new Image();
        newImg.src = image_path(prop.image);
        newImg.onload = function () {
        }
        // 返回一个对象
        return {
            nHeight: newImg.naturalHeight,
            nWidth: newImg.naturalWidth,
            nAspect: newImg.naturalWidth / newImg.naturalHeight,
            nPortrait: (newImg.naturalWidth > newImg.naturalHeight) ? false : true,
        };
    };
});
</script>

<template>
       <div>
            <span v-if="getDimensions.nPortrait">这是一张竖直的图像<br /></span>
            <span v-else>这是一张非竖直的图像<br /></span>

            <span>这张图像的高度
                {{ getDimensions.nHeight }}
            </span>
            <img class="w-full h-full
                        object-fill
                        object-center
                        rounded-lg"
            :src="image_path(prop.image)" alt=""
            >
        </div>
</template>

这段代码似乎在添加<span>标签之前正常工作。然后,结果为零或NaN。

我首先尝试将其作为箭头函数,但结果没有任何区别。
我猜测作为一个新手,我不知道这里发生了什么,导致了NaN。

英文:

I have an app that displays image arrays. Before the image is displayed I need to adjust cropping based upon the image dimensions. When I load the image in a vue child component, I use a computed function (arrow or regular) and in the browser's inspect vue extension the object value are there and correct. But when I attempt to use a computed object's parameter, the result are zero or Nan. I used both the standard computed function and the arrow computed function. Both results are the same.

script setup&gt;
import { computed } from &#39;vue&#39;;
const prop = defineProps({
image: String,
numberOfImages: {
type: Number,
default: 0,
},
});
const getDimensions = computed(function () {
get: {
const newImg = new Image();
newImg.src = image_path(prop.image);
newImg.onload = function () {
}
// returning an object
return {
nHeight: newImg.naturalHeight,
nWidth: newImg.naturalWidth,
nAspect: newImg.naturalWidth / newImg.naturalHeight,
nPortrait: (newImg.naturalWidth &gt; newImg.naturalHeight) ? false : true,
};
};
});
&lt;/script&gt;
&lt;template&gt;
&lt;div&gt;
&lt;span v-if=&quot;getDimensions.nPortrait&quot;&gt;This is a portrait Image&lt;br /&gt;&lt;/span&gt;
&lt;span v-else&gt;This is a NOT portrait Image&lt;br /&gt;&lt;/span&gt;
&lt;span&gt;This Image Height:
{{ getDimensions.nHeight }}
&lt;/span&gt;
&lt;img class=&quot;w-full h-full
object-fill
object-center
rounded-lg&quot;
:src=&quot;image_path(prop.image)&quot; alt=&quot;&quot;
&gt;
&lt;/div&gt;
&lt;/template&gt;

The code seems to work fine until I add the span tags. Then the results are zero or Nan

I first tried it as an arrow function but no difference in result.
I guess being a newbie - I just don't have a clue whats happening here to cause the NaN

答案1

得分: 1

以下是您要翻译的内容:

您正在访问 newImg 加载其 src 之前的属性,因此尺寸都为空。请注意,当 prop.image 更改时,计算属性将更新,但当 newImage 更改时不会更新,因为它不是响应式引用。

要解决此问题,将计算属性改为监视器,并使用 onload 等待图像加载完成:

const dimensions = ref({})

const loadImageDimensions = async (imageSrc) => {
  if (!imageSrc){
    return {}
  }
  const newImg = new Image()
  newImg.src = imageSrc
  await new Promise(resolve => newImg.onload = resolve)
  return {
    nHeight: newImg.naturalHeight,
    nWidth: newImg.naturalWidth,
    nAspect: newImg.naturalWidth / newImg.naturalHeight,
    nPortrait: (newImg.naturalWidth <= newImg.naturalHeight),
  }
}
watch(
 () => props.image,
 async () => dimensions.value = await loadImageDimensions(props.image),
 { immediate: true }
)

请注意,不应该使用计算属性来处理 dimensions,因为它是通过异步函数设置的,而计算属性不应该具有副作用

playground中查看示例

英文:

You are accessing the properties of newImg before it has loaded its src, so the dimensions are all empty. Note that the computed will update when prop.image changes, but not when newImage changes, as it is not a reactive reference.

To resolve the issue, turn the computed into a watcher and use the onload to wait for the image:

const dimensions = ref({})
const loadImageDimensions = async (imageSrc) =&gt; {
if (!imageSrc){
return {}
}
const newImg = new Image()
newImg.src = imageSrc
await new Promise(resolve =&gt; newImg.onload = resolve)
return {
nHeight: newImg.naturalHeight,
nWidth: newImg.naturalWidth,
nAspect: newImg.naturalWidth / newImg.naturalHeight,
nPortrait: (newImg.naturalWidth &lt;= newImg.naturalHeight),
}
}
watch(
() =&gt; props.image,
async () =&gt; dimensions.value = await loadImageDimensions(props.image),
{ immediate: true }
)

Note that you should not use a computed for dimensions since it is set through an async function, and computed properties should not have side-effects.

Here it is in a playground

huangapple
  • 本文由 发表于 2023年6月12日 03:19:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定