如何访问服务器端React中的JSX组件的DOM事件处理程序
我正在使用React构build一个简单的静态视图引擎,目标是呈现静态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>
-tag的onClick
-handler? 这甚至有可能做些什么?
为了能够从onClick事件中获得一个string的函数,我们需要以下内容:
- 元素的DOM
- 我们可以通过在我们的h1元素上附加一个ref属性来获得这个
- 传递给onClick事件的函数的名称(单击)
- 函数本身来自包含函数名称的string
- 由于我们在React组件中方便地使用了方法,我们可以在组件中使用这个['functionName']来获得函数。
- 该函数的string化版本
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> ); } }
经过大量的搞乱之后,我想出了一个很好的解决scheme。
如果我创build自己的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等)。 如果是这样,并且这个属性的值是types的函数 – 我有事件名称和它的处理函数:
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
recursion地遍历所有它的子组件,并将具有事件的每个组件添加到数组中。
剩下的唯一问题是,我需要一种方法将呈现的DOMstring绑定到我现在拥有的JavaScript处理程序。 为此,我添加了一个需要使用自定义的DOM属性,然后可以使用这样的东西来识别组件
$("[data-id=value]").on({event-name}, {it's JS-handler})
。
这可能不完美,但我认为这是最好的解决scheme。