在 React 中监听 Web 组件事件 [英] Listening for web component events in React

查看:58
本文介绍了在 React 中监听 Web 组件事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上我想要的是能够为我的聚合物按钮添加一个onTap"属性:

到目前为止,我已经尝试了以下方法.前四个不起作用,后两个我觉得非常难吃:

1) 编写自定义反应事件插件.由于多种原因,这不起作用.尽管乍一看似乎您可以将 'tap' 事件添加到 React 侦听的事件集中,但是无法扩展 ReactBrowserEventEmitter.js 中的 topEventMapping 表代码>.

(有人想知道 这段代码 是如何工作的,答案很可能是它不起作用't - 它很旧了.)

(一个相关的问题是,react 插件系统非常奇怪,它似乎竭尽全力阻止任何人添加新插件——就像你必须重置整个事件系统并重新注册所有内置的——在插件中,如果你想添加一个新的.)

2) 创建一个 mixin 类,将一个 'tap' 事件侦听器添加到 react 组件的根元素.mixin 将查看事件目标并从属性中获取处理程序函数的名称并将事件分派给它.

根据 这篇文章.所以事件监听器永远不会被触发.

3) 在窗口对象上添加一个事件侦听器,然后将事件路由到原始组件.尽管窗口侦听器确实收到了该事件,但没有方法可以在给定元素引用的情况下定位反应组件.(至少,在适用于 Meteor 1.2 的 react 版本中没有.)

4) 对所有具有 'onTap' 属性的 DOM 元素进行 querySelector 搜索,并分别为每个元素添加一个事件侦听器.这可以在 react 组件的 mixin 类中完成.

问题是无法从 querySelector 结果中排除子组件中的元素,因此如果您嵌套了 React 组件,每个组件都在其中包含 Web 组件,则事件将触发多个处理程序.

5) 将每个 Web 组件包装在一个 React 组件中.虽然这是 React 推荐的方法,但它的工作量很大(我使用了数十个 Polymer 组件,每个组件都有许多属性)并且在代码膨胀和反惯用语方面效率低下 - 生成的 HTML 代码看起来不再像 Polymer 代码.

6) 使用ref"获取对每个 Web 组件的引用,并手动为每个组件添加一个侦听器.这有效,但它很丑陋并且使代码混乱很多(请记住,您还必须取消订阅).我想要onTap"的全部原因是我可以避免编写所有这些样板.

解决方案

您可以尝试使用 xeact.

import xeact, {dispatchEvent, Component} from 'xeact';@xeact('纸按钮')导出默认类 PaperButton 扩展组件 {句柄Tap(){dispatchEvent(this, 'tap' , {数据});}使成为() {return 

{this.handleTap()}}/>}}

然后将其用作 html 中的 web 组件

<脚本>document.querySelector('x-paper-button').addEventListener('tap',功能(){//点击})

Basically what I want is to be able to add an 'onTap' attribute to my polymer button:

<paper-button onTap={this.handleTap}></paper-button>

So far I've tried the following approaches. The first four don't work, and the last two I find extremely unpalatable:

1) Write a custom react event plugin. This doesn't work for several reasons. Although at first glance it appears that you could add the 'tap' event to the set of events that React listens for, but there's no way to extend the topEventMapping table in ReactBrowserEventEmitter.js.

(One wonders how this code could possibly work, and the answer is likely that it doesn't - it's old.)

(A related problem is that the react plugin system is very weird, it seems to go out of its way to prevent anyone from adding new plugins - like you have to reset the entire event system and re-register all the built-in plugins if you want to add a new one.)

2) Create a mixin class that adds a 'tap' event listener to the root element of a react component. The mixin would look at the event target and get the name of the handler function from the attribute and dispatch the event to it.

This doesn't work because events originating from web components don't propagate to react components correctly, according to this article. So the event listener is never triggered.

3) Add an event listener on the window object and then route the event to the originating component. Although the event does get received by the window listener, there's no method to locate a react component given an element reference. (At least, not in the version of react that works with Meteor 1.2.)

4) Do a querySelector search on all DOM elements that have an 'onTap' attribute, and add an event listener on each one individually. This could be done in a mixin class to the react component.

The problem is that there's no way to exclude elements in child components from the querySelector results, so if you have nested react components each having web components inside of them, the events will trigger multiple handlers.

5) Wrap every web component in a react component. While this is the approach recommended by React, it's a huge amount of work (I'm using dozens of Polymer components, each of which has many attributes) and it's both inefficient in terms of code bloat and anti-idiomatic - the resulting HTML code no longer looks like Polymer code.

6) Use 'ref' to get a reference to each web component and manually add a listener to each one. This works, but it's ugly and clutters up the code a lot (remember you also have to unsubscribe as well). My whole reason for wanting 'onTap' is to that I can avoid having to write all this boilerplate.

解决方案

You can try to use xeact.

import xeact, {dispatchEvent, Component} from 'xeact';

@xeact('paper-button')
export default class PaperButton extends Component {

    handleTap() {
        dispatchEvent(this, 'tap' , {
            data
        });
    }

    render() {
        return <div onClick={() => {this.handleTap()}} />
    }
}

then use it as web-components in html

<x-paper-button></x-paper-button>
<script>
    document.querySelector('x-paper-button').addEventListener('tap', 
    function(){
        // onTap
    })
</script>

这篇关于在 React 中监听 Web 组件事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆