组件用.vue还是.js
by Cathy Ha
由凯茜·哈(Cathy Ha)
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存储库中的所有代码。
I created the component with the following goals in mind:
我在创建组件时考虑了以下目标:
One file at a time (note that this tutorial talks about how to handle multiple files — all you need are some loops)
一次一个文件(请注意, 本教程讨论了如何处理多个文件-您只需要一些循环即可)
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
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>
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的“插槽”功能。
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.一旦用户从文件选择器中选择了某些内容/关闭了文件选择器,我们需要检查:
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)发送到父组件。
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>
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显示提示上传或头像预览。
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
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态