如何在React中处理事件

时间:2017-07-26 17:18:04

标签: javascript reactjs

我有简单的hello world代码:

import React from 'react';

class ShoppingList extends React.Component {

    getComponent(event) {
        console.log('li item clicked!');
        event.currentTarget.style.backgroundColor = '#ccc';
    }

    render() {
        return (

            <div className="shopping-list">
                <h1>This is props name: {this.props.name}</h1>
                <ul>
                    <li>Item 1</li>
                    <li>Item 2</li>
                    <li>Item 3</li>
                </ul>
                <div>
                    <ul>
                        <li onClick={this.getComponent.bind(this)}>Component 1</li>
                    </ul>
                </div>
            </div>

        );
    }
}

module.exports = ShoppingList;

当我点击<li>Component 1</li>时,没有任何反应。

为什么呢?页面成功呈现。没有错误,
一切 没问题,但处理程序无法正常工作。

FULL EXAMPLE

节点服务器: app.js

var express = require('express');
var app = express();

var routes = require('./routes/index')

app.use('/', routes);

app.set('port', process.env.PORT || 9080);

app.use('/public', express.static(__dirname + '/public/'));

app.set('views', __dirname + '/views');
app.set('view engine', 'jsx');
app.engine('jsx', require('express-react-views').createEngine());

var server = app.listen(app.get('port'), function () {
    console.log(__dirname + '/public/');
    console.log('STARTED');
});

路线: index.js:

var express = require('express');

var router = express.Router();

router.get('/', function (req, res) {
    res.render('index', {name:"AHOJ"});
});

module.exports = router;

index.jsx:

import React from 'react';


var ShoppingList = require('./components/ShoppingList');

class IndexComponent extends React.Component {
    constructor(props) {
        super(props);
        this.getComponent = this.getComponent.bind(this);
    }

    getComponent(event) {
        console.log('li item clicked!');
        event.currentTarget.style.backgroundColor = '#ccc';
    }
    render() {
        return (

            <DefaultLayout name={this.props.name}>
                <div>
                    <ul>
                        <li onClick={this.getComponent}>Component 1</li>
                    </ul>
                </div>
            </DefaultLayout>

        )
    }
};

module.exports = IndexComponent;

master.jsx:

var React = require('react');

class MasterLayout extends React.Component {
    render() {
        return (
            <html lang="eng">
                <head>
                    <meta charset="utf-8" />

                    <title>{this.props.name}</title>
                    <meta name="description" content="The HTML5 Herald" />
                    <meta name="author" content="SitePoint" />
                    <link rel="stylesheet" type="text/css" href="/public/css/main.css" />
                </head>
                <body>
                    {this.props.children}
                </body>
            </html>
        )
    }
};

module.exports = MasterLayout;

我希望,这个代码对你来说很明确,它的hello world项目。完整示例是课程ShoppingListIndexComponent

我阅读了一些教程,我认为,我的代码是正确的,页面成功呈现。没有错误,
一切 没问题,但处理程序无法正常工作。

<li> 数据重新

3 个答案:

答案 0 :(得分:3)

这不是你应该如何构建你的组件。这样做:

class ShoppingList extends React.Component {
    constructor(props) {
        super(props);
        this.getComponent = this.getComponent.bind(this);
    }

    getComponent(event) {
        console.log('li item clicked!');
        event.currentTarget.style.backgroundColor = '#ccc';
    }

    render() {
        return (
            <div className="shopping-list">
                <h1>This is props name: {this.props.name}</h1>
                <ul>
                    <li>Item 1</li>
                    <li>Item 2</li>
                    <li>Item 3</li>
                </ul>
                <div>
                    <ul>
                        <li onClick={this.getComponent}>Component 1</li>
                    </ul>
                </div>
            </div>
        );
    }
}

我在这里做的是为组件创建了一个构造函数。构造函数调用super(),以便它可以使用this关键字。

  

在构造函数中使用时,super关键字单独出现,必须在使用this关键字之前使用。此关键字也可用于调用父对象上的函数。

然后,它调用.bind(this)并将getComponent绑定到组件。现在onClick处理程序可以更改为onClick={this.getComponent}。将对.bind()的调用移动到构造函数会提供显着的性能提升,因为现在该方法只绑定一次,而不是在每次渲染组件时反复绑定。

额外提示:getComponent的参数名称从event更改为其他内容。 event不是JS中的保留关键字,但它 但在某些IE版本中是全局的。追踪相当棘手的错误。

答案 1 :(得分:1)

只是一个FYI,您还可以使用无状态功能组件并使用存储在常量中的方法:

import React from 'react';
import { render } from 'react-dom';

const clickHandler = e => {
  console.log(`${e.target} \n element clicked!!! \n -------`);
};

const App = () => (
  <div>
    <ul>
      <li style={{border:"solid 1px"}}
        onClick={clickHandler}
      >Click Me</li>
    </ul>
    <h2 onClick={clickHandler}>I'm a header</h2>
  </div>
);

render(<App />, document.getElementById('root'));

如果您点击<li>控制台将显示:

[object HTMLLIElement] 
 element clicked!!! 
 -------

如果您单击标题,它将显示:

[object HTMLHeadingElement] 
 element clicked!!! 
 -------

但是当然如果您需要扩展组件类,您可以使用它,但如果您使用目标而不是当前目标,则不需要创建构造函数:

https://developer.mozilla.org/es/docs/Web/API/Event/currentTarget

这是没有构造函数的代码:

import React, {Component} from 'react';
import { render } from 'react-dom';

class App extends Component {

  clickHandler(e){
    console.log(e.target);
    e.target.style.backgroundColor = '#ccc';
  }

  render(){
    return(
      <div>
        <ul>
          <li style={{border:"solid 1px"}}
            onClick={this.clickHandler}
          >Click Me</li>
        </ul>
        <h2 onClick={this.clickHandler}>I'm a header</h2>
      </div>
    );
  }

}

render(<App />, document.getElementById('root'));

正如您所看到的,它适用于两种情况:

https://codesandbox.io/s/nZY3W5x0p

答案 2 :(得分:0)

将你的李改为:

<li onClick={() => this.getComponent}>Component 1</li>

这种方式在实际点击时会正确引用它,而不是在渲染时引用它。