从设计模式入手,介绍Blob
、FileReader
。
虚拟代理模式
当提及虚拟代理
时,你可能下意识的会想到proxy
,虚拟代理的核心思想就是在目标对象身上架设起一座桥梁,为它去做一些额外的事。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const target = { message1: "hello", message2: "everyone" };
const handler3 = { get (target, prop, receiver) { console.log(target, prop, receiver) if (prop === "message2") { return "world"; } return Reflect.get(...arguments); },
set (target, prop, receiver) { console.log('set', prop, target, receiver, this) if (prop === 'message1') { target[prop] = receiver } } };
const proxy3 = new Proxy(target, handler3);
proxy3.message1 = 'ssdsd'
console.log(proxy3.message1); console.log(proxy3.message2);
|
粘贴了MDN
的Proxy
示例,配合Reflect
去做一些既保留原始行为,又可以自定义行为的功能。
同样的,虚拟代理的原理也很简单,拿一个图片的预加载
举一个栗子
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class TDomObj { constructor(obj) { this.trueDom = obj; }
setSrc (url) { this.trueDom.src = url } } class ProxyTDom { constructor(TDom) { this.TDom = TDom; }
setSrc (url) { this.TDom.setSrc('https://segmentfault.com/img/bVbIDbC'); const img = new Image(); img.onload = () => { this.TDom.setSrc(url); } img.src = url; } }
|
那么,有人会问了,这些跟 Blob
、FileReader
有什么关系呢?
FileReader
FileReader
可以读取用户计算机上的二进制文件。以Blob
对象的数据格式去处理。
怎么获取用户计算机文件呢?
利用input
手动上传,监听change
;
利用ajax
获取服务端文件,可以设置responseType
为Blob
对象。
(小tip
: 阿里 OSS
的图片、文件(pdf等)CDN
是不支持预览的,可以借助ajax
获取服务端文件,以Blob
形式获取后,创建Blob URL
,利用createObjectURL(:blob)
生成,window.open
预览)
Blob
Blob
是一种原始数据对象(其实就是二进制数据对象);【File
继承自Blob
】
File
继承自Blob
,所以也就可以引申我们接下来要提到的,图片分片上传
,利用Blob
对象的splice
方法,它可以返回一个新的Blob
对象。
相比于一般的base 64
的 data url
而言,Blob Url
更短,字节数更少,所以文件也就很少,可以作为提升性能的一个手段,但是它的局限性在于只能在当前应用内使用,应为生成的Blob URL
前缀为当前应用的根路径。不可以跨应用使用。
Now, Show My Time!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title>
</head> <body> <input type="file" placeholder="请上传" id="UPLOAD"> <img id="OUTPUT" src=""/> <script> class TDomObj { constructor(obj) { this.trueDom = obj; }
setSrc (url) { this.trueDom.src = url } }
class ProxyTDom { constructor(TDom) { this.TDom = TDom; }
setSrc (url) { this.TDom.setSrc('https://segmentfault.com/img/bVbIDbC'); const img = new Image(); img.onload = () => { this.TDom.setSrc(url); } img.src = url; } }
const tdom = document.getElementById('OUTPUT');
const t = new TDomObj(tdom);
const p = new ProxyTDom(t);
document.getElementById('UPLOAD').addEventListener('change', (e) => { console.log(e); const reader = new FileReader(); reader.onload = function () { console.log(reader.result) p.setSrc(reader.result) } reader.readAsDataURL(e.target.files[0]); }) </script> </body> </html>
|