图片上传预览场景基本处处可见, 朋友圈发动态配图, 身份验证及头像更新, 莫过如斯.
原由
最近在研究 Twitter PC 网站的时候, 在个人中心的主页, 设置个人的背景图的时候, 发现 Twitter 有个非常好的设计, 那就是用户在更改背景墙图片的时候, 它根本不是先上传图片, 而是在本地预览及编辑图片, 待用户点击保存后, 才上传图片, 可以说是非常省流量的啦. 然后, 我在玩知乎的时候貌似它是先上传, 然后预览的, 为啥不学 Twitter 这样做呢? 于是乎, 我就研究了下图片预览的几种方式, 跟大家一起分享下.
介绍几个不常见的 BOM 对象
URL 对象
URL 对象是浏览器的原生对象, 可以用来构造, 解析及编码 URL. 一般情况下, 通过 Windows.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, 你瞅我干啥);
FileReader 对象
FileReader 对象呢, 在此不再赘述, 因为一谈到图片上传, 那必须要用到的. 具体可以参看 MDN 的 API 文档了.
这个对象的兼容性, 基本上也不用怎么考虑. 除非个别的如 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 = Windows.URL.createObjectURL(file);
- target.onload = function () {
- Windows.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