原由

最近在研究twitter PC网站的时候,在个人中心的主页,设置个人的背景图的时候,发现twitter有个非常好的设计,那就是用户在更改背景墙图片的时候,它根本不是先上传图片,而是在本地预览及编辑图片,待用户点击保存后,才上传图片,可以说是非常省流量的啦。然后,我在玩知乎的时候貌似它是先上传,然后预览的,为啥不学twitter这样做呢?于是乎,我就研究了下图片预览的几种方式,跟大家一起分享下。
图片上传预览方式,了解下?-LMLPHP

介绍几个不常见的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,你瞅我干啥);
图片上传预览方式,了解下?-LMLPHP

FileReader对象

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

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

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

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

最后,如果你如果觉得我的文章不错的话,麻烦关注下我的个人公众号【前端汇聚】。
图片上传预览方式,了解下?-LMLPHP

05-17 03:31