组件用.vue还是.js_如何使用Vue.js 2.0构建灵活的图像上传器组件

 2023-09-06 阅读 20 评论 0

摘要:组件用.vue还是.jsby Cathy Ha 由凯茜哈(Cathy Ha) 如何使用Vue.js 2.0构建灵活的图像上传器组件 (How to build a flexible image uploader component using Vue.js 2.0) I’ve been coding with Vue.js 2.0 for about half a year now, and it’s pretty awesome. It’s inc

组件用.vue还是.js

by Cathy Ha

由凯茜·哈(Cathy Ha)

如何使用Vue.js 2.0构建灵活的图像上传器组件 (How to build a flexible image uploader component using Vue.js 2.0)

I’ve been coding with Vue.js 2.0 for about half a year now, and it’s pretty awesome. It’s incredibly intuitive and simple. The partitioning between HTML/CSS/Javascript makes both learning and coding a breeze.

我已经使用Vue.js 2.0编码了大约半年了,这非常棒。 这是非常直观和简单的。 HTML / CSS / Javascript之间的分区使学习和编码变得轻而易举。

But the trouble (and the fun) of coding with a relatively new framework is the lack of tutorials for what you want to build. Especially when you have a specific thing in mind.

但是,使用相对较新的框架进行编码的麻烦(也很有趣)是缺少想要构建的教程。 特别是当您有特定的想法时。

I ran into this issue when I was trying to build a profile photo uploader for Torneo. Sure, I could have used a fancy package, but where’s the fun in that?

当我尝试为Torneo构建个人资料照片上传程序时遇到了这个问题。 当然,我本可以使用精美的包装,但是这样做的乐趣在哪里?

So, by modifying and combining two great tutorials, I created my own reusable image uploader component.

因此,通过修改和组合两个 出色的教程,我创建了自己的可重用图像上传器组件

Check out the git repository for all the code.

检出git存储库中的所有代码。

期望的行为 (Desired Behaviour)

I created the component with the following goals in mind:

我在创建组件时考虑了以下目标:

  • The component should be capable of being activated by any element in its parent component to upload images

    该组件应该能够被其父组件中的任何元素激活以上传图像
  • We should be able to see a preview of the image in the parent component

    我们应该能够在父组件中看到图像的预览
  • The uploaded image should be saved in a FormData format to send to the back-end

    上传的图像应以FormData格式保存,以发送到后端
  • The component should check for a size limit in the uploaded image (this can be done in the back-end as well, but it’s a bit faster in the front-end)

    该组件应检查上传图像中的大小限制(这也可以在后端完成,但是在前端要快一些)
  • One file at a time (note that this tutorial talks about how to handle multiple files — all you need are some loops)

    一次一个文件(请注意, 本教程讨论了如何处理多个文件-您只需要一些循环即可)

步骤1:设定 (Step 1: Setup)

We’ll get started by installing the webpack-simple template. We’ll also be installing Vuetify to save some time on styling. Note that everything wrapped in <v-…> is from Vuetify. Since their tags are pretty self-explanatory, I won’t go too deep into it. I will leave you to read their documentation.

我们将从安装webpack-simple模板开始。 我们还将安装Vuetify,以节省样式时间。 请注意,<v-…>中包装的所有内容均来自Vuetify。 由于它们的标签是不言自明的,因此我不会对其进行深入研究。 我将让您阅读他们的文档。

# install the vue-clinpm install vue-cli -g# initiate the webpack-simple, and follow instructionsvue init webpack-simple image-upload
# install dependenciesnpm install
# install Vuetifynpm install vuetify --save

步骤2:建立图片上载范本 (Step 2: Create the Image Upload Template)

Great! Now that we have the templates set up and installed, we can delete any placeholder content. Then we can create a new component file for the image uploader.

大! 现在我们已经设置并安装了模板,我们可以删除任何占位符内容。 然后,我们可以为图像上传器创建一个新的组件文件。

<template>  <div>
<!-- slot for parent component to activate the file changer -->    <div @click="launchFilePicker()">      <slot name="activator"></slot>    </div>
<!-- image input: style is set to hidden and assigned a ref so that it can be triggered -->    <input type="file"       ref="file"       :name="uploadFieldName"       @change="onFileChange(          $event.target.name, $event.target.files)"       style="display:none">
<!-- error dialog displays any potential errors -->    <v-dialog v-model="errorDialog" max-width="300">      <v-card>        <v-card-text class="subheading">{{errorText}}</v-card-text>        <v-card-actions>          <v-spacer></v-spacer>          <v-btn @click="errorDialog = false" flat>Got it!</v-btn>        </v-card-actions>      </v-card>    </v-dialog>
</div></template>
  1. To make the image uploader component capable of being activated by any element in the parent component, we can take advantage of Vue’s “slot” functionality.

    为了使图像上载器组件能够被父组件中的任何元素激活,我们可以利用Vue的“插槽”功能。

  2. Since we want the “trigger” for the input to be in the parent component, we want the functionality of the file input in the child component, without being able to see it. We can change the style of the input to “display:none” to hide it.

    由于我们希望输入的“触发器”位于父组件中,因此我们希望子组件中文件输入的功能无法看到。 我们可以将输入的样式更改为“ display:none”以将其隐藏。
  3. The image input is assigned a “ref” so that when the slot is clicked on, we can activate the image input by its reference.

    为图像输入分配了一个“参考”,以便在单击插槽时可以通过其参考激活图像输入。
  4. To make the image uploader more user-friendly, we can use a dialog to display any potential errors.

    为了使图像上传器更加用户友好,我们可以使用对话框来显示任何潜在的错误。

Next, we can use some Vue.js magic in the JavaScript portion to massage some life into our component:

接下来,我们可以在JavaScript部分中使用一些Vue.js魔术来为我们的组件增加生命:

<script>
export default {
name: 'image-input',
data: ()=> ({      errorDialog: null,      errorText: '',      uploadFieldName: 'file',      maxSize: 1024    }),
props: {          // Use "value" here to enable compatibility with v-model      value: Object,    },
methods: {      launchFilePicker(){        this.$refs.file.click();      },
onFileChange(fieldName, file) {        const { maxSize } = this        let imageFile = file[0]          //check if user actually selected a file        if (file.length>0) {          let size = imageFile.size / maxSize / maxSize          if (!imageFile.type.match('image.*')) {            // check whether the upload is an image            this.errorDialog = true            this.errorText = 'Please choose an image file'          } else if (size>1) {            // check whether the size is greater than the size limit            this.errorDialog = true            this.errorText = 'Your file is too big! Please select an image under 1MB'          } else {            // Append file into FormData & turn file into image URL            let formData = new FormData()            let imageURL = URL.createObjectURL(imageFile)            formData.append(fieldName, imageFile)
// Emit FormData & image URL to the parent component            this.$emit('input', { formData, imageURL })          }        }      }    }  }</script>

5. To make the image uploader component v-model compatible, use “value” in the props. Whatever data that is emitted by the component will be captured in the “value” prop.

5.要使图像上传器组件的v模型兼容,请在道具中使用“值”。 组件发出的任何数据都将在“值”属性中捕获。

6. When the file input activator in the parent component is clicked, “this.$refs.file.click()” is used to activate the file selector.

6.单击父组件中的文件输入激活器时,“ this。$ refs.file.click()”用于激活文件选择器。

7. Once the user picks something from the file selector / closes the file selector, we need to check:

7.一旦用户从文件选择器中选择了某些内容/关闭了文件选择器,我们需要检查:

  • Whether the user has actually selected a file

    用户是否实际选择了文件
  • Whether the file is an image

    该文件是否为图像
  • Whether the file is greater than the size limit (often a good idea when it comes to user uploads)

    文件是否大于大小限制(关于用户上传,通常是个好主意)

8. If the file that the user selected is fine, create a FormData element and append the file into the element using a name that your server would accept. Also, convert the image file into an object URL so that the parent component can read it for a preview.

8.如果用户选择的文件很好,请创建一个FormData元素,然后使用服务器可以接受的名称将该文件附加到该元素中。 另外,将图像文件转换为对象URL,以便父组件可以读取该文件以进行预览。

9. Emit the data (FormData for uploading to the server, and imageURL for the preview) to the parent component.

9.将数据(用于上传到服务器的FormData和用于预览的imageURL)发送到父组件。

步骤3:创建父组件 (Step 3: Create the Parent Component)

In the parent component, we can visualize the child component’s functionality.

在父组件中,我们可以可视化子组件的功能。

<template>  <v-app id="app" class="mt-0">    <v-container grid-list-xl>      <image-input v-model="avatar">        <div slot="activator">          <v-avatar size="150px" v-ripple v-if="!avatar" class="grey lighten-3 mb-3">            <span>Click to add avatar</span>          </v-avatar>          <v-avatar size="150px" v-ripple v-else class="mb-3">            <img :src="avatar.imageURL" alt="avatar">          </v-avatar>        </div>      </image-input>      <v-slide-x-transition>        <div v-if="avatar && saved == false">          <v-btn class="primary" @click="uploadImage" :loading="saving">Save Avatar</v-btn>        </div>      </v-slide-x-transition>    </v-container>  </v-app></template>
  1. Wrap the activator element in a <div/> and let the child component know that it belongs in the slot that we named “activator”.

    将激活器元素包装在<div />中,并让子组件知道它属于我们称为“激活器”的插槽中。
  2. Use Vue’s v-if and v-else to display a prompt to upload or the avatar preview depending on whether the user has selected a file.

    根据用户是否选择了文件,使用Vue的v-if和v-else显示提示上传或头像预览。

  3. Conditionally display a button to save the user’s changes.

    有条件地显示一个按钮来保存用户的更改。

Almost done! Next, time to add in some Javascript to the parent component:

快完成了! 接下来,是时候向父组件添加一些Javascript了:

<script>import ImageInput from './components/ImageInput.vue'
export default {  name: 'app',  data () {    return {      avatar: null,      saving: false,      saved: false    }  },  components: {    ImageInput: ImageInput  },  watch:{    avatar: {      handler: function() {        this.saved = false      },      deep: true    }  },  methods: {    uploadImage() {      this.saving = true      setTimeout(() => this.savedAvatar(), 1000)    },    savedAvatar() {      this.saving = false      this.saved = true    }  }}</script>

4. In the script portion, import the child component.

4.在脚本部分中,导入子组件。

5. When the user clicks “save”, upload the avatar to the server (note that I am faking an upload in the code above. In reality, we use axios to upload the file to the server. The back-end then saves the file in a filesystem and passes the path to the file in the data).

5.当用户单击“保存”时,将头像上传到服务器(请注意,我在上面的代码中伪造了一个上传。实际上,我们使用axios将文件上传到服务器。后端然后保存文件系统中的文件,并将路径传递到数据中的文件)。

That’s it! There’s much room to enhance this component — like passing props to resize the image being uploaded, handling multiple files, etc. If you see any potential points for improvement or spot a mistake in my code, please please leave a comment!

而已! 增强此组件的空间很大,例如传递道具以调整要上传的图像的大小,处理多个文件等。如果您发现任何潜在的改进点或在我的代码中发现错误,请发表评论!

Again, feel free to check out the git repository for all the code.

再次,随时检查git存储库中的所有代码。

Finally, a shameless plug here: if you happen to be interested in sports, check out Torneo — a sports-related startup that I’ve helped to develop.

最后,这里是一个无耻的插件:如果您对体育感兴趣,请访问Torneo ,这是我帮助开发的与体育相关的初创公司。

翻译自: https://www.freecodecamp.org/news/how-to-build-a-flexible-image-uploader-component-using-vue-js-2-0-5ee7fc77516/

组件用.vue还是.js

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/7573.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息