【问题标题】:How to access DOM event-handlers for JSX-components in server-sided React如何在服务器端 React 中访问 JSX 组件的 DOM 事件处理程序
【发布时间】:2018-03-23 15:31:22
【问题描述】:

我正在使用 React 构建一个简单的静态视图引擎,目的是呈现静态 HTML 标记并生成一个填充了该组件 DOM 事件(onClick 等)的 js 文件。

我做第一部分的方式是要求一个指定的 JSX 文件,例如,它看起来像这样:

import React from 'React';

export default class Test extends React.Component {

    clicked() {
        alert('Clicked the header!');
    }

    render() {
        return (
            <html>
                <head>
                    <title>{this.props.title}</title>
                </head>
                <body>
                    <h1 onClick={this.clicked}>click me!!!</h1>
                </body>
            </html>
        );
    }
}

然后我通过 NodeJS 后端渲染 JSX 文件,如下所示:

let view = require('path-to-the-jsx-file');
view = view.default || view;

const ViewElement = React.createFactory(view);
let output = ReactDOMServer.renderToStaticMarkup(ViewElement(props));

它非常适合提供静态 HTML。但是我想知道是否有一种方法可以访问数组或其他东西中 JSX 文件中使用的所有组件,然后我可以使用它来检查绑定了哪些事件以及哪些处理程序。

那么在这个例子中,能够得到&lt;h1&gt;-tag 的onClick-handler 吗?这甚至有可能以某种方式做到吗?

【问题讨论】:

    标签: javascript node.js reactjs jsx


    【解决方案1】:

    为了能够从 onClick 事件中以字符串形式获取函数,我们需要以下内容:

    1. 元素的 DOM
      • 我们可以通过在我们的 h1 元素上附加一个ref 属性来获得它
    2. 传递到 onClick 事件(单击)的函数的名称
    3. 函数本身来自包含函数名称的字符串
      • 由于我们在 React 组件中方便地使用方法,我们可以在组件中使用 this['functionName'] 来获取函数。
    4. 函数的字符串化版本

    import React from 'React';
    
    export default class Test extends React.Component {
        componentDidMount() {
    
            // Gets the name of the function passed inside onClick()
            const nameBound = this.element.props.onClick.name;
    
            // Removes 'bound ' from the function name (-> clicked)
            const nameString = nameBound.replace('bound ', '');
    
            // Gets the function from the function name as a string
            const convertedFunction = this[nameString];
    
            // Converts the function into string
            const stringifiedFunction = convertedFunction.toString();
            console.log(functionString);
        }
    
        clicked() {
            alert('Clicked the header!');
        }
    
        render() {
            return (
                <html>
                    <head>
                        <title>{this.props.title}</title>
                    </head>
                    <body>
                        <h1 ref={(element) => { this.element = element; }} onClick={this.clicked}>click me!!!</h1>
                    </body>
                </html>
            );
        }
    }
    

    【讨论】:

    • 这可以工作,但很难维护。想象一下,该组件中有 5-10 个处理程序。而且我不确定你如何能够将这些数据返回到后端,除非你有一个主组件,它有一个以某种方式做到这一点的功能。
    【解决方案2】:

    经过大量的折腾,我想出了一个效果很好的解决方案。

    如果我创建自己想要渲染的 ReactElement 实例(在示例中为 ViewElement(props)),然后我可以使用它的标准 render-function 渲染元素:

    let element = ViewElement(props);
    let instance = new element.type();
    let render = instance.render();
    

    从这里我可以浏览这个元素的所有道具,比如onClick-handlers 将在render.props

    所以我要做的是检查每个道具是否与反应事件名称匹配(例如 onClick、onDragEnd、onDragEnter 等)。如果是这样,并且此属性的值是函数类型 - 我有事件名称 并且 它是处理函数:

    Object.keys(render.props).map((key) => {
        if (bigArrayOfAllTheEventNames.indexOf(key) !== -1) {
            item.events[key] = render.props[key];//check if type is function.
        }
    });
    

    然后我还递归遍历 render.props.children 以访问它的所有子组件并将每个具有事件的组件添加到数组中。

    剩下的唯一问题是我需要一种方法将呈现的 DOM 字符串绑定到我现在拥有的 javascript 处理程序。为此,我添加了使用自定义 DOM 属性的需求,然后可以使用它来标识组件,例如

    $("[data-id=value]").on({event-name}, {it's JS-handler}).

    它可能还不完美,但我认为这是最好的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-26
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      • 2017-04-04
      相关资源
      最近更新 更多