在vue中使用input上传图片(及隐藏input按钮使其更加美观)| 青训营笔记

582 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第10天.

背景:

在大项目中遇到了这样一个需求,上传图片并展示.然而使用input标签上传在页面上的效果并不美观,后来发现有一种方法能够美化页面效果.

方法:

1.html部分代码

                <div class="click_pictures_container">
                    <input type="file" multiple @change="upload" id="batchUpload">
                    <!-- 图片展示栏 -->
                    <div class="view">
                        <li v-for="(item, index) in picturelist" :key="index">
                            <img :src="item">
                            <div class="delect" @click="delect(index)">×</div>
                        </li>
                    </div>

                </div>

为input标签绑定change事件upload通过该事件去读取上传的文件并将数据转存到data中,然后再通过v-for列表渲染将这些图片渲染到前端页面.

2.js部分代码

        upload(e) {
            //e.target指向事件执行时鼠标所点击区域的那个元素,那么为input的标签,
            // 可以输出 e.target.files 看看,这个files对象保存着选中的所有的图片的信息。
            console.log(e.target.files)
            //------------------------------------------------------     
            // 既然如此,循环这个files对象,用for of 循环,     
            for (let item of e.target.files) {
                //正则表达式,判断每个元素的type属性是否为图片形式,如图
                if (!/image\/\w+/.test(item.type)) {
                    // 提示只能是图片,return
                    alert("只能选择图片");
                    return;
                }
                // 保存下当前 this ,就是vue实例
                var _this = this;
                //  创建一个FileReader()对象,它里面有个readAsDataURL方法
                let reader = new FileReader();
                // readAsDataURL方法可以将上传的图片格式转为base64,然后在存入到图片路径, 
                //这样就可以上传电脑任意位置的图片                            
                reader.readAsDataURL(item);
                //文件读取成功完成时触发
                reader.addEventListener('load', function () {
                    //  reader.result返回文件的内容。
                    //只有在读取操作完成后,此属性才有效,返回的数据的格式取决于是使用哪种读取方法来执行读取操作的。
                    //给数组添加这个文件也就是图片的内容
                    _this.picturelist.push(this.result)
                })
            }

        },
        
         data() {
        return {
          
            picturelist: [],
        }
    },

在js函数中首先遍历标签的files属性,将刚才上传的文件进行类型检测,如果不是图片类型就弹出alert警告并结束函数,如果成功遍历完所有上传文件 发现都是图片就将其转换为64位格式以存在列表picturelist中.并在html部分src中引用.

效果:

image.png
很明显,效果并不美观,无论是按钮样式还是后面跟随显示的 x个文件 都影响观看效果.为了更加美观我们可以将input按钮隐藏,然后自定义一个按钮来代替原本的按钮.

优化策略:

我们可以在input标签的下方写一个div标签,并采用绝对定位的方法将该标签置于input标签上方,将其覆盖.并将div标签绑定点击事件,在事件中触发input标签的点击事件.

html部分代码:

                <div class="click_pictures_container">
                    <input type="file" multiple @change="upload" id="batchUpload">
                    <!-- 采用绝对定位,隐藏input,达到隐藏已上传几个图片的效果 -->
                    <div class="upload" @click="centerUploadBox">上传图片</div>
                    <!-- 图片展示栏 -->
                    <div class="view">
                        <li v-for="(item, index) in picturelist" :key="index">
                            <img :src="item">
                            <div class="delect" @click="delect(index)">×</div>
                        </li>
                    </div>

                </div>

js部分代码:

 //通过点击div,对input进行触发click事件,进而点击div盒子时,可以触发input
        centerUploadBox() {
            var batchUpload = document.querySelector('#batchUpload');
            batchUpload.click();
        }

效果图:

image.png