![601bc2944f32679ee5d3fcffd4d596cd.png](https://i-blog.csdnimg.cn/blog_migrate/b3170114fe6bcfd34f0920d157cfd8c8.jpeg)
图片上传预览场景基本处处可见,朋友圈发动态配图,身份验证及头像更新,莫过如斯。
原由
最近在研究twitter PC网站的时候,在个人中心的主页,设置个人的背景图的时候,发现twitter有个非常好的设计,那就是用户在更改背景墙图片的时候,它根本不是先上传图片,而是在本地预览及编辑图片,待用户点击保存后,才上传图片,可以说是非常省流量的啦。然后,我在玩知乎的时候貌似它是先上传,然后预览的,为啥不学twitter这样做呢?于是乎,我就研究了下图片预览的几种方式,跟大家一起分享下。
介绍几个不常见的BOM对象
URL对象
- URL对象是浏览器的原生对象,可以用来构造、解析及编码URL。一般情况下,通过window.URL可以拿到这个对象。
<a>
元素及<area>
元素都部署了这个接口。也就是说,它们的 DOM 节点对象可以使用 URL 的实例属性和方法。
var a = document.createElement('a');
a.href = 'https://www.baidu.com?search=bat';
console.log(a.hostname); // www.baidu.com
console.log(a.search); // ?search=bat
上面代码中,a是<a>
元素的 DOM 节点对象。可以在这个对象上使用 URL 的实例属性,比如hostname和search。
- URL是一个构造函数,可以生成URL实例。它接受一个表示 URL 的字符串作为参数。如果参数不是合法的 URL,会报错。
var url = new URL('http://www.example.com/index.html');
console.log(url.href);
// "http://www.example.com/index.html"
如果参数是另一个 URL 实例,构造函数会自动读取该实例的href属性,作为实际参数。如果 URL 字符串是一个相对路径,那么需要表示绝对路径的第二个参数,作为计算基准。
- 实例属性
URL 实例的属性与Location对象的属性基本一致,返回当前 URL 的信息。
- URL.href:返回整个 URL
- URL.protocol:返回协议,以冒号:结尾
- URL.hostname:返回域名
- URL.host:返回域名与端口,包含:号,默认的80和443端口会省略
- URL.port:返回端口
- URL.origin:返回协议、域名和端口
- URL.pathname:返回路径,以斜杠/开头
- URL.search:返回查询字符串,以问号?开头
- URL.searchParams:返回一个URLSearchParams实例,该属性是Location对象没有的
- URL.hash:返回片段识别符,以井号#开头
- URL.password:返回域名前面的密码
- URL.username:返回域名前面的用户名
- 静态方法createObjectURL()
URL.createObjectURL方法用来为上传/下载的文件、流媒体文件生成一个URL字符串。这个字符串代表了File对象或Blob对象的URL。
URL.createObjectURL方法用来为上传的文件生成一个 URL 字符串,作为元素的图片来源。注意,每次使用URL.createObjectURL方法,都会在内存里面生成一个 URL 实例。如果不再需要该方法生成的 URL 字符串,为了节省内存,可以使用URL.revokeObjectURL()方法释放这个实例.
- 静态方法 revokeObjectURL()
URL.revokeObjectURL
方法用来释放URL.createObjectURL
方法生成的 URL 实例。它的参数就是URL.createObjectURL
方法返回的 URL 字符串。
那么,大家关心的一个问题就是它的兼容性问题了,可以说移动端基本上是没啥问题的啦。除了个别的(IE,你瞅我干啥)。
![7e1e0a48535539e601785a9e085e98ea.png](https://i-blog.csdnimg.cn/blog_migrate/a55d19a86d2354ad7a6aa986d263a565.jpeg)
FileReader对象
FileReader
对象呢,在此不再赘述,因为一谈到图片上传,那必须要用到的。具体可以参看MDN的API文档了FileReader。
这个对象的兼容性,基本上也不用怎么考虑。除非个别的如IE6-9等等。
![ccaa387e24fe365c06aa43632654a5c3.png](https://i-blog.csdnimg.cn/blog_migrate/c7c51527ea259c8212cbe5dd4d1ddfd8.jpeg)
实例演示图片预览的几种方法
经过上述对两个对象的了解,那么大家可能知道,我们预览可能会跟这两个对象有关,毋庸置疑,那是必须要的。
<!--html-->
<img id="preview" src="" />
<input type="file" id="select" accept="iamge/png,iamge/jpeg,image/jpg" />
var preview = document.getElementById('preview'),
select = document.getElementById('select');
select.addEventListener('change', function fileInput (e) {
if (!this.files.length) return
var file = this.files[0];
previewImage(preview, file);
}, false);
- 第一种,也就是twttier使用的方式:
function previewImage (target, file) {
try {
var src = window.URL.createObjectURL(file);
target.onload = function () {
window.URL.revokeObjectURL(this.src);
};
target.src = src;
} catch (e) {
throw new Error('browser doest not support URL')
}
}
- 第二种,使用
FileReader
对象readAsDataURL
方法:
function previewImage (target, file) {
try {
var fileReader = new FileReader();
fileReader.onload = function (e) {
target.src = e.target.result
};
fileReader.readAsDataURL(file);
} catch (e) {
throw new Error('browser doest not support FileReader')
}
};
- 第三种,针对IE的,经了解,在IE7-11下,文件上传地址为本地的绝对路径地址,因此可一直直接将图片路径直接设置为input的值
select.addEventListener('change', function fileInput (e) {
if (!this.files.length) return
// 具体要在IE浏览器验证下
preivew.src = this.value;
}, false);
最后,如果你如果觉得我的文章不错的话,麻烦关注下我的个人公众号【前端汇聚】。
![055bb5d7d5034156fee8df7d1dfe8487.png](https://i-blog.csdnimg.cn/blog_migrate/2dbd38e6e94e1d026cb0b8c1ab0b0401.jpeg)