VuesJS Form和Rails 5.1中的文件上载错误



我的Rails 5.1应用程序中有一个使用Vuejs构建的表单。除了文件上传,我的所有字段都能很好地工作,并将数据持久化到数据库中。我得到错误

[Vue warn]: Error compiling template:打印在控制台顶部,然后基本上是我的整个模板代码,然后是

- <input v-model="variation.photo_one" type="file">: File inputs are read only. Use a v-on:change listener instead.

我是Vuejs的新手,即使在阅读了许多其他关于这方面的在线帖子后,我也不知道如何让它发挥作用。

_form.html.erb

<%= content_tag :div,
id: "product-form",
data: {
id: product.id,
product: product.to_json(except: [:id, :created_at, :updated_at]),
variations_attributes: product.variations.to_json(except: [:product_id, :created_at, :updated_at]),
} do %>
...
<div class="col-md-4 upload-block">
<label>Photo One</label>  
<input type="file" v-model="variation.photo_one" style="margin-bottom: .5em">
</div>
...
<% end %>

app_vue.js

import Vue from 'vue/dist/vue.esm'
import TurbolinksAdapter from 'vue-turbolinks'
import VueResource from 'vue-resource'
Vue.use(VueResource)
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
Vue.http.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
var element = document.getElementById("product-form")
if (element != null) {
var id = element.dataset.id
var product = JSON.parse(element.dataset.product)
var variations_attributes = JSON.parse(element.dataset.variationsAttributes)
variations_attributes.forEach(function(variation) { variation._destroy = null })
product.variations_attributes = variations_attributes
var app = new Vue({
el: element,
data: function() {
return { id: id, product: product }
},
methods: {
addVariation: function() {
this.product.variations_attributes.push({
id: null,
name: "",
photo_one: "",
//position: "",
_destroy: null
})
},
removeVariation: function(index) {
var variation = this.product.variations_attributes[index]
if (variation.id == null) {
this.product.variations_attributes.splice(index, 1)
} else {
this.product.variations_attributes[index]._destroy = "1"
}
},
undoRemove: function(index) {
this.product.variations_attributes[index]._destroy = null
},
saveProduct: function() {
// Create a new product
if (this.id == null) {
this.$http.post('/products', { product: this.product }).then(response => {
Turbolinks.visit(`/products/${response.body.id}`)
}, response => {
console.log(response)
})
// Edit an existing product
} else {
this.$http.put(`/products/${this.id}`, { product: this.product }).then(response => {
Turbolinks.visit(`/products/${response.body.id}`)
}, response => {
console.log(response)
})
}
},
existingProduct: function() {
return this.product.id != null
}
}
})
}
})

文件在Vue中有点尴尬。正如消息所说,不能将v-model用于具有type="file"的输入。相反,您必须使用change事件并调用组件中的方法来手动处理该文件。

<input type="file" @change="handleFileChange" />
methods: {
handleFileChange(event) {
//you can access the file in using event.target.files[0]
this.fileField = event.target.files[0];
}
}

当您提交AJAX请求时,您可能需要提交FormData对象,而不是提交javascript对象。MDN文档对如何使用它进行了解释。我发现FormData是处理文件上传时比较尴尬的部分。https://developer.mozilla.org/en-US/docs/Web/API/FormData