How to access DOM event

I am building a simple static view-engine using React with the goal of rendering static HTML-markup and generating a js-file filled with that components DOM-events (onClick, etc).

The way I'm doing the first part is to require a specified JSX-file which, for example, looks like this:

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

I am then rendering the JSX-file via a NodeJS-backend like this:

let view = require('path-to-the-jsx-file');
view = view.default || view;

const ViewElement = React.createFactory(view);
let output = ReactDOMServer.renderToStaticMarkup(ViewElement(props));

It works great for serving static HTML. But I am wondering if there is a way to access all components used in the JSX-file in an array or something, which I then could use to check what events are bound and to which handlers.

So in this example, be able to get that the <h1> -tag's onClick -handler? Is this even possible to do somehow?


To be able to get the function as a string from the onClick event, we want the following:

  • The DOM of the element
  • We can obtain this by attaching a ref attribute on our h1 element
  • The name of the function being passed into the onClick event (clicked)
  • The function itself from a string containing the name of the function
  • Since we're conveniently using methods within a React component, we can use this['functionName'] within our component to obtain the function.
  • A stringified version of the function

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

    After a lot of messing around I came up with a solution that works quite well.

    If I create my own instance of the ReactElement I want to render (in the example ViewElement(props) ), I can then render the element using it's standard render -function:

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

    From here I can go through all the props for this element, so, say, onClick -handlers would be in render.props .

    So what I do is to check each prop if the key matches a react-event-name (ex. onClick, onDragEnd, onDragEnter etc). If it does, and the value of this property is of type function - I have the event-name and it's handler-function:

    Object.keys(render.props).map((key) => {
        if (bigArrayOfAllTheEventNames.indexOf(key) !== -1) {
            item.events[key] = render.props[key];//check if type is function.
        }
    });
    

    Then I also iterate through the render.props.children recursivly to reach all it's child components and add every component which has events to an array.

    The only problem left was that I needed a way to bind the rendered DOM-string to the javascript handlers I now have. For this I added a need to use a custom DOM-attribute, which then can be used to ID the component with something like this

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

    It might not be perfect yet, but I think that this is the best solution out there.

    链接地址: http://www.djcxy.com/p/52152.html

    上一篇: 回应最佳做法/使用父组件实例

    下一篇: 如何访问DOM事件