图片上传预览方式,了解下?

图片上传预览场景基本处处可见,朋友圈发动态配图,身份验证及头像更新,莫过如斯。

原由

最近在研究twitter PC网站的时候,在个人中心的主页,设置个人的背景图的时候,发现twitter有个非常好的设计,那就是用户在更改背景墙图片的时候,它根本不是先上传图片,而是在本地预览及编辑图片,待用户点击保存后,才上传图片,可以说是非常省流量的啦。然后,我在玩知乎的时候貌似它是先上传,然后预览的,为啥不学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');
    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:返回域名前面的用户名
  • 静态方法

    • URL.createObjectURL()
      URL.createObjectURL方法用来为上传/下载的文件、流媒体文件生成一个URL字符串。这个字符串代表了File对象或Blob对象的 URL
      URL.createObjectURL方法用来为上传的文件生成一个 URL 字符串,作为元素的图片来源。注意,每次使用URL.createObjectURL方法,都会在内存里面生成一个 URL 实例。如果不再需要该方法生成的 URL 字符串,为了节省内存,可以使用URL.revokeObjectURL()方法释放这个实例。
    • URL.revokeObjectURL()
      URL.revokeObjectURL方法用来释放URL.createObjectURL方法生成的 URL 实例。它的参数就是URL.createObjectURL方法返回的 URL 字符串。

那么,大家关心的一个问题就是它的兼容性问题了,可以说移动端基本上是没啥问题的啦。除了个别的(IE,你瞅我干啥);
can I use

FileReader对象

FileReader对象呢,在此不再赘述,因为一谈到图片上传,那必须要用到的。具体可以参看MDN的API文档了FileReader
这个对象的兼容性,基本上也不用怎么考虑。除非个别的如IE6-9等等。
在这里插入图片描述

实例演示图片预览的几种方法

经过上述对两个对象的了解,那么大家可能知道,我们预览可能会跟这两个对象有关,毋庸置疑,那是必须要的。

<!--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);

最后,如果你如果觉得我的文章不错的话,麻烦关注下我的个人公众号【前端汇聚】。
前端汇聚

原文地址:https://www.cnblogs.com/jlienzen/p/10877427.html