首页 文章

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

提问于
浏览
10

我正在使用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> -tag的 onClick -handler?这有可能以某种方式吗?

2 回答

  • 2

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

    • 元素的DOM

    • 我们可以通过在我们的h1元素上附加ref属性来获得它

    • 传递给onClick事件的函数的名称(单击)

    • 函数本身来自包含函数名称的字符串

    • 我们在我们的组件中获取函数're conveniently using methods within a React component, we can use this[' functionName'] .

    • 函数的字符串化版本


    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>
            );
        }
    }
    
  • 2

    在一片混乱之后,我提出了一个非常有效的解决方案 .

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

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

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

    所以我要做的是检查每个prop是否匹配react-event-name(例如onClick,onDragEnd,onDragEnter等) . 如果是,并且此属性的值是函数类型 - 我有事件名 and 它的处理函数:

    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}) .

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

相关问题