如何在服务器端的React中访问JSX组件的DOM事件处理程序

时间:2017-10-11 20:29:23

标签: javascript node.js reactjs jsx

我正在使用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-backend渲染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文件中使用的所有组件,然后我可以使用它来检查绑定的事件和哪些处理程序。

所以在这个例子中,能够得到<h1> - 标签的onClick - 处理程序吗?这有可能以某种方式吗?

2 个答案:

答案 0 :(得分:2)

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

  1. 元素的DOM
    • 我们可以通过在我们的h1元素
    • 上附加ref属性来获得此功能
  2. 传递给onClick事件(单击)
  3. 的函数的名称
  4. 函数本身来自包含函数名称的字符串
    • 由于我们可以方便地使用React组件中的方法,因此我们可以在组件中使用此[&#39; functionName&#39;]来获取该功能。
  5. 函数的字符串化版本
  6. 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>
            );
        }
    }
    

答案 1 :(得分:2)

经过一段时间的很多后,我想出了一个效果很好的解决方案。

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

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

从这里我可以浏览这个元素的所有道具,比方说,onClick - 处理程序将在render.props

所以我要做的是检查每个prop是否匹配react-event-name(例如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 recursivly来到达它的所有子组件,并将每个包含事件的组件添加到数组中。

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

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

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