之前写过一篇关于img
添加自定义请求头的处理方式(点击这里),那么本篇我们来看另外几种实现方法。
以Vue
为例,我们可以定义一个全局指令,对img
标签进行一些处理。
<template>
<img :src="src" v-getImage>
template>
Vue.directive('getImage', {
// 插入
inserted(el,binding,vnode){
let src = el.getAttribute('src');
requestImage(src).then(res=>{
el.setAttribute('src',res)
});
},
// 更新
update(el,binding,vnode){
let src = el.getAttribute('src')
vnode.context.getImage(src).then(res=>{
el.setAttribute('src',res)
});
},
// 解绑
unbind(el) {
URL.revokeObjectURL(el.getAttribute('src'));
}
})
图像加载过程中发生错误时会触发onerror
事件。
我们可以利用这一点来实现手动拦截,主动发起请求并处理数据后,将file
或blob
对象重新赋值给到src
即可。
简单示例如下:
<img src="xxx" onerror="handleError()">
// 错误处理
function handleError() {
const oriImg = event.target;
// 手动发起请求
requestImage(oriImg.currentSrc);
// 避免死循环
oriImg.onerror = null;
}
扩展img-src
的set
方法。示例如下:
// 自定义请求
function requestImage(url){
//...
}
// 扩展原有src行为
function hookImage() {
const property = Object.getOwnPropertyDescriptor(Image.prototype, 'src');
const nativeSet = property.set;
Object.defineProperty(Image.prototype, 'src', {
set: function(url){
if (url.indexOf('image/view')>-1) {
requestImage(url).then(res=>{
// 将处理后的src传入,执行原有默认逻辑
nativeSet.call(this, URL.createObjectURL(res));
});
}else{
nativeSet.call(this, url);
}
},
});
}
hookImage()
这个方法主要针对一般页面中的图片。
扩展Element-setAttribute
方法。示例如下:
// 自定义请求
function requestImage(url){
//...
}
// 扩展原有setAttribute行为
function hookImage() {
// 记录原生方法
const rawSetAttribute = Element.prototype.setAttribute
// 重写setAttribute
Element.prototype.setAttribute = function setAttribute (key, value) {
if (key == 'src' && value.indexOf('image/view')>-1) {
requestImage(value).then(res=>{
// 将处理后的src传入,执行原有默认逻辑
rawSetAttribute.call(this, key, URL.createObjectURL(res))
})
} else {
rawSetAttribute.call(this, key, value)
}
}
}
hookImage()
这个方法主要针对富文本编辑器中的图片。
扩展HTMLDocument-execCommand
方法。示例如下:
// 自定义请求
function requestImage(url){
//...
}
// 扩展原有execCommand行为
function hookImage() {
// 图片正则
const reg = / /gi;
// 匹配图片src
const srcreg = /
]*src=['"]([^'"]+)[^>]*>/gi;
// 记录原生方法
const rawSetExecCommand = HTMLDocument.prototype.execCommand
// 重写setAttribute
HTMLDocument.prototype.execCommand = function execCommand (key,bool, value) {
// 一般富文本编辑器使用的图片插入是insertHTML指令,这里匹配img标签
if (key == 'insertHTML') {
// 如果是图片
if(reg.test(value)){
// 获取src
value.replace(srcreg, (match, capture)=> {
if(capture){
requestImage(capture).then(res=>{
// 替换src为blob对象
let imgStr = value.replace(srcreg,`
${URL.createObjectURL(res)}\' alt="自定义插入图片">`)
// 将处理后的src传入,执行原有默认逻辑
rawSetExecCommand.call(this, key, bool, imgStr)
})
}
});
}
} else {
rawSetExecCommand.call(this, key, bool, value)
}
}
}
hookImage()
img
标签单独处理,改动量比较大。https
,那么只需要使用service worker
即可。