【问题标题】:File upload in vuetify [closed]在 vuetify 中上传文件 [关闭]
【发布时间】:2017-12-12 20:05:34
【问题描述】:

我在 Vue.js 中为我的前端使用 Vuetify.js 组件,并希望创建一个带有文件上传的用户注册表单。我可以使用 v-text-field(一个 Vuetify 组件)创建表单。

  • 如何上传选中(输入)的文件?
  • 我应该使用哪个组件或有其他替代方法?

【问题讨论】:

  • 您可以使用常规的 AJAX 发布请求来上传表单。
  • 我想在 vuetify 中上传文件如何像图片上传一样上传

标签: javascript frameworks vue.js vuetify.js


【解决方案1】:

这是我们将来会添加的内容,但目前不会。在 github 上有讨论,有几个用户发布了他们暂时使用的实现,https://github.com/vuetifyjs/vuetify/issues/238

【讨论】:

    【解决方案2】:

    Vue JS 直到今天还没有文件输入功能,因此您可以调整 v-text-field 使其像图像输入字段一样工作。概念是,创建一个文件输入字段,然后使用 css 将其隐藏,并在 v-text-field 中添加一个事件以触发该特定文件输入字段以上传图像。我附上了 sn-p,请你玩一下,我也有一个使用 vue 和 vuetify 创建的小提琴,请访问here。谢谢!

    new Vue({
      el: '#app',
      data: () => ({
        title: "Image Upload",
        dialog: false,
        imageName: '',
        imageUrl: '',
        imageFile: ''
      }),
    
      methods: {
        pickFile() {
          this.$refs.image.click()
        },
    
        onFilePicked(e) {
          const files = e.target.files
          if (files[0] !== undefined) {
            this.imageName = files[0].name
            if (this.imageName.lastIndexOf('.') <= 0) {
              return
            }
            const fr = new FileReader()
            fr.readAsDataURL(files[0])
            fr.addEventListener('load', () => {
              this.imageUrl = fr.result
              this.imageFile = files[0] // this is an image file that can be sent to server...
            })
          } else {
            this.imageName = ''
            this.imageFile = ''
            this.imageUrl = ''
          }
        }
      }
    })
    <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
    <link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet">
    <div id="app">
      <v-app>
        <v-toolbar dark color="primary">
          <v-toolbar-side-icon></v-toolbar-side-icon>
          <v-toolbar-title class="white--text">{{ title }}</v-toolbar-title>
          <v-spacer></v-spacer>
          <v-btn icon @click="dialog = !dialog">
            <v-icon>link</v-icon>
          </v-btn>
        </v-toolbar>
        <v-content>
          <v-container fluid>
            <v-flex xs12 class="text-xs-center text-sm-center text-md-center text-lg-center">
              <img :src="imageUrl" height="150" v-if="imageUrl"/>
              <v-text-field label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field>
              <input
                type="file"
                style="display: none"
                ref="image"
                accept="image/*"
                @change="onFilePicked"
              >
            </v-flex>
            <v-dialog v-model="dialog" max-width="290">
              <v-card>
                <v-card-title class="headline">Hello World!</v-card-title>
                <v-card-text>
                  Image Upload Script in VUE JS
                  <hr>
                  Yubaraj Shrestha
                  <br>http://yubarajshrestha.com.np/
                </v-card-text>
                <v-card-actions>
                  <v-spacer></v-spacer>
                  <v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Close</v-btn>
                </v-card-actions>
              </v-card>
            </v-dialog>
          </v-container>
        </v-content>
      </v-app>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>

    最新版本 (V2.0.5) 在编辑这篇日期为 2019 年 8 月 11 日的帖子时,有一个专用的文件输入选项。请点击以下链接获取官方文档:https://vuetifyjs.com/en/components/file-inputs.

    【讨论】:

    • 对于 v-text-field 中的点击功能,我必须这样做 @click.stop="pickFile" 才能让它工作
    • 在过去的几个月里,我一直在使用这个解决方案,顺便说一下,它看起来非常干净整洁,我们刚刚开始注意到一些奇怪的行为。上传文档后,@change="onFilePicked" 事件似乎没有触发,并将文件的 v-text-field 留空。有没有人看到过类似的行为?
    • 避免对“数据”使用箭头函数。在简单的场景中它会起作用,但如果你需要 vue 实例中的一些值,它会破坏代码,因为箭头函数中的 'this' 并不指向 vue 实例。
    • @YubarajShrestha 对于那些可能只是从 Stackoverflow 复制+粘贴+扩展代码的人来说,最好指出这一点。 this 使用内部数据与 id : this.$route.params.id 之类的路由参数结合使用相当普遍 - 已经看到很多这样的做法。
    • @Hexodus :) 谢谢你的建议。您对您展示的路线案例是绝对正确的,这完全取决于开发人员的舒适度。与常见用例相比,我更喜欢可读性更好,因此我将这些路由参数放在计算属性中,并为其命名,以便从长远来看更好地理解系统。
    【解决方案3】:

    一个简单的技巧是:

    <v-btn color="success" @click="$refs.inputUpload.click()">Success</v-btn>
    <input v-show="false" ref="inputUpload" type="file" @change="yourFunction" >
    

    只需创建一个具有以下属性的输入:

    • type=file
    • ref=inputUpload 这就像一个 id,你可以随意命名
    • v-show=false 这隐藏了输入

    然后制作一个按钮,当您单击它时,它会在输入上传按钮上触发一个单击事件。

    【讨论】:

    • 哈哈“它看起来像个笑话” - 我有点震惊 Vuetify 没有涵盖文件输入,谢谢你的技巧:-)
    • 很好的解决方案!谢谢你.. 只需要一个更新.. btn 上的@click 需要是这样的:$refs.inputUpload.$el.click() 只需要$el,它就像一个冠军!
    【解决方案4】:

    好消息。

    从版本 2.0.0.-beta.8 v-file-input 开始在 Vuetify 中可用。你应该像这样使用它:

    <template>
      <v-file-input accept=".txt" label="Select File..."></v-file-input>
    </template>
    

    编辑(片段添加):

    处理图像文件的基本用法可以实现如下。

    感谢@Begueradj 指出,甚至不需要处理@change 事件来跟踪文件更改并使示例更加精确:

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data: () => ({
        file: null,
        imageUrl: null
      }),
      methods: {
        onUpload() {
          console.log(this.file)
        }
      }
    })
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@3.x/css/materialdesignicons.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    
    <div id="app">
      <v-app>
        <v-content>
          <v-container>
            <v-file-input 
              v-model="file" 
              label="Select Image File..." 
              accept="image/*"
            ></v-file-input>
            <v-btn color="primary" @click="onUpload">Upload</v-btn>
          </v-container>
        </v-content>
      </v-app>
    </div>

    【讨论】:

    • 如何将此文件发送到我的服务器?
    • 您可以处理带有v-file-inputv-model 属性的文件。我添加了一个记录文件的示例,您可以将其发送到服务器。
    • 尝试运行时输出 [Vue warn]: Error in beforeCreate hook: "TypeError: t.observable is not a function"
    • 你为什么要添加onFileChange()函数?
    • @Begueradj 你是对的:变化检测实际上是开箱即用的v-file-input。编辑了答案。
    猜你喜欢
    • 2019-03-09
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    相关资源
    最近更新 更多