Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
447 views
in Technique[技术] by (71.8m points)

javascript - 代理事件目标上的addEventListener(addEventListener on proxied Event Target)

I'm trying to create an object that is basically both a Proxy and an EventTarget .

(我正在尝试创建一个基本上既是Proxy又是EventTarget 。)

The goal is to be able to subscribe to any changes made to this object.

(目的是能够订阅对此对象所做的任何更改。)

Here's how I define this object:

(这是我定义此对象的方式:)

const target = new EventTarget()
const state = new Proxy(target, { 
    set: (obj, key, value) => { 
        Reflect.set(obj, key, value)
        obj.dispatchEvent(new CustomEvent('change', {detail: {key, value}}))
    }, 
    deleteProperty: (obj, key) => { 
        Reflect.deleteProperty(obj, key) 
        obj.dispatchEvent(new CustomEvent('change', {detail: {key, value: undefined}})) 
    } 
})

At this point I'd like to be able to call state.addEventListener('change', console.log) but this gives me an error:

(此时,我希望能够调用state.addEventListener('change', console.log)但这给了我一个错误:)

Uncaught TypeError: Illegal invocation

(未捕获的TypeError:非法调用)

So here's what works:

(所以这是有效的:)

target.addEventListener('change', console.log)
state.foo = 'bar'
// logs the event

But as I said, I'd like to have one single unified object that can be both the target (can be listened to with addEventListener ) and the store of values (proxied object in charge of dispatching the events when modified).

(但是正如我所说,我希望有一个单一的统一对象,它既可以作为目标(可以使用addEventListener监听)又可以作为值的存储(代理对象,修改后用于调度事件)。)

So far, this method only works if you carry around both target and state ...

(到目前为止,如果你随身携带两个这种方法只适用targetstate ...)

Any idea why I can't call addEventListener by going through the Proxy ?

(知道为什么我无法通过Proxy调用addEventListener吗?)


Technically, calling state.addEventListener() goes through the get prototype method, so I tried defining get: Reflect.get in the proxy handler but it adds nothing... (Even though it was indeed reached because I tried adding a console.log there too)

(从技术上讲,调用state.addEventListener()会通过get原型方法进行,因此我尝试在代理处理程序中定义get: Reflect.get ,但未添加任何内容...(即使确实达到了,因为我尝试添加console.log那里))

So why can't I call addEventListener through the proxy but it works fine directly on the target object?

(那么,为什么不能通过代理调用addEventListener ,但是直接在target对象上可以正常工作呢?)

  ask by Sheraff translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Oh, nevermind... I found the answer... Still posting it though, as it wasn't as straightforward for me as I would have hoped and it might help someone.

(哦,没关系...我找到了答案...虽然仍然在发布它,因为它对我而言并不像我希望的那么简单,它可能会对某人有所帮助。)


The issue is that when the proxy returns a function, the function doesn't have the proper scope ( this ).

(问题是,当代理返回一个函数时,该函数没有适当的作用域( this )。)

So you need to bind the proper scope to the returned function.

(因此,您需要将适当的范围绑定到返回的函数。)

This can be done by defining a getter:

(这可以通过定义一个吸气剂来完成:)

    get: function (obj, key) {
        const result = Reflect.get(obj, key)
        if(typeof result === 'function')
            return result.bind(obj)
        return result
    }

Once this is done, it's as simple as this:

(一旦完成,就这么简单:)

const state = new Proxy(new EventTarget(), handler)
state.addEventListener('change', console.log)
state.foo = 'bar'
// logs the event

On a W3C recommendations level, I am unsure as to why a Proxy shouldn't return functions with their proper scope...

(在W3C建议级别上,我不确定为什么Proxy不应该返回具有适当范围的函数...)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...