2017-10-11 20 views
10

我使用React构建了一个简单的静态视图引擎,其目标是呈现静态HTML标记并生成一个填充了该组件的js文件(onClick等)。如何在服务器端访问JSX组件的DOM事件处理程序React

我做的第一部分的方法是需要一个指定的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?这甚至有可能做些什么?

回答

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属性,然后可以使用此类ID来识别组件。

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

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

2

为了能够得到该函数为onClick事件的字符串,我们要执行以下操作:

  1. 元素的DOM
    • 我们可以通过附加ref属性上获得此
  2. 函数的名称被传递到onClick事件我们h1元素(点击)
  3. 乐趣ction本身来自包含函数名称的字符串
    • 由于我们在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> 
     ); 
    } 
} 
+0

这会工作,但它会很难维护。想象一下,在这个组件中有5-10个处理程序。而且我不确定你怎么能够将这些数据返回到后端,除非你喜欢一个具有这种功能的主组件。 – Tokfrans

相关问题