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



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

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

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

  1. 元素的DOM
    • 我们可以通过在h1元素上附加ref属性来获得它
  2. 传递到onClick事件中的函数的名称(单击)
  3. 函数本身来自包含函数名称的字符串
    • 由于我们很方便地在React组件中使用方法,我们可以在组件中使用这个["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>
);
}
}

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

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

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

从这里,我可以浏览这个元素的所有道具,比如说,onClick-处理程序将在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})

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

最新更新