Question
How to create a proxy for browser native DOM object?
Background
I want to intercept the settings for the element style. So I create a proxy for the DOM object. However, it causes error when I use some function like getComputedStyle()
.
const setHandler = (target: any, prop: PropertyKey, value: any, _receiver?: any) => {
if (/*some condition*/) {
target[prop] = value
}
return true
}
const getHandler = (target: any, prop: PropertyKey, _receiver?: any) => {
return target[prop]
}
const style = new Proxy(el.style, {
get: getHandler,
set: setHandler
})
const classList = new Proxy(el.classList,{
get: getHandler,
set: setHandler
})
const proxy = new Proxy(el/*HTMLElement*/, {
get: (target, prop, _receiver) => {
if (prop === 'target') {
return target
}
if (prop === 'style') {
return style
}
if (prop === 'classList') {
return classList
}
return getHandler(target, prop, target)
},
set: setHandler
})
const style = getComputedStyle(el)
el
is the native browser DOM object. In my code, there are many methods whose parameters are el
, and these methods may modify el.
I want to prevent some of these methods from modifying el
, so I am trying to proxy the el
object.
But after the proxy, some methods for DOM objects can't be used on proxy objects (like getComputedStyle()
).
Demo
I create a demo below.
(function() {
const node = document.querySelector('#demo')
const proxy = new Proxy(node, {
getPrototypeOf(target){
return Object.getPrototypeOf(target)
},
get(target, prop, receiver){
let value = target[prop]
if (typeof value === 'function') {
value = Function.prototype.bind.call(value, target)
}
return value
},
set(target, prop,value, receiver){
target[prop] = value
},
apply(target, args, newTarget) {
return Object.apply(target,args)
},
})
console.log(proxy)
console.log(Object.getPrototypeOf(proxy))
console.log(proxy.style)
// error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
const style = getComputedStyle(proxy)
console.log(style)
})()
<div id='demo'>demo</div>