Vue JS通过v-model上的文件上传器设置图像应用空对象
Posted
技术标签:
【中文标题】Vue JS通过v-model上的文件上传器设置图像应用空对象【英文标题】:Vue JS setting image through file uploader on v-model applies empty object 【发布时间】:2022-01-06 10:10:18 【问题描述】:我正在使用 Vue JS 2 创建图像上传器。我的输入有一个change
函数,它运行一个函数并将我的文件设置在v-model
属性上。
当我console.log
我的数据时,所有设置的是一个空对象而不是图像,这也导致我的 Vee 验证规则失败,因为它认为它是空的。
我错过了什么?
用于上传徽标的 html
<validation-observer ref="brandCreationForm" v-slot=" handleSubmit ">
<form class="space-y-6" @submit.stop.prevent="handleSubmit(create)">
<validation-observer :key="1" class="space-y-6">
<pre>
form
</pre>
<div>
<validation-provider
name="brand"
rules="required"
v-slot=" errors, classes "
>
<label for="brand" class="block text-sm font-medium text-gray-500 mb-2">Brand name</label>
<div class="mt-1 relative rounded-md shadow-sm">
<input v-model="form.brand" type="text" name="brand" id="brand" :class="classes" class="focus:ring-green-500 focus:border-green-500 block w-full py-3 px-4 sm:text-sm border border-gray-300 rounded-md" placeholder="my brand name">
</div>
<span class="text-xs text-red-500"> errors[0] </span>
</validation-provider>
</div>
<section v-if="form.brand != '' && form.url != ''" class="space-y-6 pl-6">
<div>
<validation-provider
name="brand_logo"
rules="mimes:image/jpeg,image/png"
v-slot=" errors, classes, validate "
>
<label for="brand_logo" class="block text-sm font-medium text-gray-500 mb-2">
Brand logo <em>(PNG or JPG)</em>
</label>
<div class="mt-1 relative rounded-md shadow-sm">
<input @change="uploadImage('brand_logo', $event.target.files[0]); validate()" type="file" name="brand_logo" id="brand_logo" :class="classes" class="focus:ring-green-500 focus:border-green-500 block w-full py-3 px-4 sm:text-sm border border-gray-300 rounded-md" accept="image/png, image/jpeg">
</div>
<span class="text-xs text-red-500"> errors[0] </span>
</validation-provider>
</div>
<div>
<validation-provider
name="brand_favicon"
rules="mimes:image/jpeg,image/png"
v-slot=" errors, classes, validate "
>
<label for="brand_favicon" class="block text-sm font-medium text-gray-500 mb-2">
Brand favicon <em>(PNG or JPG)</em>
</label>
<div class="mt-1 relative rounded-md shadow-sm">
<input @change="uploadImage('brand_favicon', $event.target.files[0]); validate()" type="file" name="brand_favicon" id="brand_favicon" :class="classes" class="focus:ring-green-500 focus:border-green-500 block w-full py-3 px-4 sm:text-sm border border-gray-300 rounded-md" accept="image/png, image/jpeg">
</div>
<span class="text-xs text-red-500"> errors[0] </span>
</validation-provider>
</div>
</section>
<div class="flex justify-end">
<button type="submit" class="group relative flex justify-center py-3 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-green-500 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-20">
<div class="inline-flex">
<svg v-if="isSaving" class="animate-spin -ml-1 mr-3 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Create brand
</div>
</button>
</div>
<Alert
v-if="feedback.isShown"
:message="feedback.message"
:variant="feedback.variant" />
</validation-observer>
</form>
</validation-observer>
以下函数运行:
<script>
export default
layout: 'account',
data ()
return
isSaving: false,
form:
brand: '',
url: '',
telephone: '',
link_terms: '',
link_privacy: '',
brand_logo: null,
brand_favicon: null,
seo_description: '',
text_marketing: '',
text_promos: '',
text_broker: '',
text_footer_1: '',
text_footer_2: '',
text_credit_disclaimer: '',
analytics_system_id: '',
analytics_brand_id: ''
,
feedback:
message: '',
variant: '',
isShown: false
,
methods:
/*
** Create
*/
create ()
this.feedback.isShown = false
this.isSaving = true
this.$axios.post(`$this.$config.apiUrl/api/brands`, this.form,
timeout: 30 * 1000
).then((res) =>
setTimeout(() =>
this.$router.push('/account/brands/')
, 500)
).finally(() =>
this.isSaving = false
)
,
/*
** Select files to upload (file uploader)
*/
uploadImage (model, file)
const form = new FormData()
form.append(model, file, file.name)
this.form[model] = form
</script>
哪个form
现在应该包含与我的图像相关的所有内容,但是在添加图像时,它显示为一个空对象(见附件)
在设置我的模型之前,我也尝试过JSON.stringify
,这里也没有运气。
【问题讨论】:
你试过这种东西吗? academind.com/tutorials/vue-image-upload 另外,您需要记住 Vue2 中的 caveats for arrays。尝试将状态设置为单个状态以进行调试。 是的,试过了,我在我的函数中创建了一个form
变量,并完成了form.append('image', file, file.name)
但是当控制台记录form
时,它是空的,我需要将它添加到我的form
请求
上次我做这个的时候,我可能遇到过类似的事情。如果通过 HTTP 发送文件会发生什么?你看到请求负载中的内容了吗?
我不能单独发送图像。它们必须是我原始帖子截图中form
对象的一部分。如果通过 http 发送它们将起作用,但是我如何将整个请求与其他所有内容结合起来?
你在使用FormData吗?上次用过,效果不错。也许可以阅读this one。
【参考方案1】:
formData
对象属性都是函数,因此在模板中呈现为空对象。为了在模板中显示 formData 内容,您必须调用其原型函数之一,并显示其结果。
<div v-for="item in form.brand_logo.values()">
item
</div>
正如您在codesandbox 中看到的那样,选择文件后,它会显示在模板和控制台中。
由于我已经简化了很多你的代码,并且只保留了 formData 的东西,也许你应该创建一个可重现的示例。
【讨论】:
当然,但是如果是这种情况,为什么(当我提交表单时)它是空的?我的后端,Laravel 甚至在我记录值时说这里也是空的 一个问题可能是不正确的内容类型标题。使用 axios 发布时,它会从发布数据中推断内容类型。在您的情况下,它将是 application/json,因为 form 是一个对象,并且多部分内容将被忽略。我认为您应该尝试将所有form
对象变成一个 formData 对象,或者拆分请求,并分别发送文件。您不能混合使用 json 和多部分请求正文。以上是关于Vue JS通过v-model上的文件上传器设置图像应用空对象的主要内容,如果未能解决你的问题,请参考以下文章