【问题标题】:React js onClick can't pass value to methodReact js onClick无法将值传递给方法
【发布时间】:2015-06-30 21:34:29
【问题描述】:

我想阅读 onClick 事件值属性。但是当我点击它时,我在控制台上看到这样的东西:

SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target

我的代码工作正常。当我运行时,我可以看到{column},但无法在 onClick 事件中获取它。

我的代码:

var HeaderRows = React.createClass({
  handleSort:  function(value) {
    console.log(value);
  },
  render: function () {
    var that = this;
    return(
      <tr>
        {this.props.defaultColumns.map(function (column) {
          return (
            <th value={column} onClick={that.handleSort} >{column}</th>
          );
        })}
        {this.props.externalColumns.map(function (column) {
          // Multi dimension array - 0 is column name
          var externalColumnName = column[0];
          return ( <th>{externalColumnName}</th>);
        })}
      </tr>
    );
  }
});

如何在 React js 中将值传递给 onClick 事件?

【问题讨论】:

  • 考虑使用 self 而不是那个。这是相当误导的,因为它应该是“这个”的同义词(虽然并不重要,但对每个人来说都是如此)
  • 使用绑定方法和箭头方法我们可以将值传递给 Onclick 事件
  • 同意@WiredPrairie 和那个叫ZenMaster 的人的解释准确有效。

标签: javascript reactjs


【解决方案1】:

简单的方法

使用箭头函数:

return (
  <th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);

这将创建一个使用正确参数调用 handleSort 的新函数。

更好的方法

Extract it into a sub-component. 在渲染调用中使用箭头函数的问题是它每次都会创建一个新函数,最终导致不必要的重新渲染。

如果你创建一个子组件,你可以传递 handler 并使用 props 作为参数,只有当 props 改变时才会重新渲染(因为 handler 引用现在永远不会改变):

子组件

class TableHeader extends Component {
  handleClick = () => {
    this.props.onHeaderClick(this.props.value);
  }

  render() {
    return (
      <th onClick={this.handleClick}>
        {this.props.column}
      </th>
    );
  }
}

主要组件

{this.props.defaultColumns.map((column) => (
  <TableHeader
    value={column}
    onHeaderClick={this.handleSort}
  />
))}

旧的简单方法(ES5)

使用.bind 传递您想要的参数,这样您就可以将函数与组件上下文绑定:

return (
  <th value={column} onClick={this.handleSort.bind(this, column)}>{column}</th>
);

【讨论】:

  • 当我像您的代码一样使用时,react 会发出警告。我将代码更改为 onClick={that.onClick.bind(null,column)}
  • 如何将它与需要传递事件的&lt;a&gt; 标记一起使用,以便使用preventDefault()
  • @SimonH 该事件将作为最后一个参数传递,在您通过 bind 传递的参数之后。
  • 这对性能来说不是坏事吗?每次渲染都会创建一个新函数吗?
  • @AndrewMcLagan 是的。我found this来描述规则和最高效的解决方案。
【解决方案2】:

现在,有了 ES6,我觉得我们可以使用更新的答案。

return (
  <th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);

基本上,(对于任何不知道的人)因为onClick 期待一个传递给它的函数,bind 有效,因为它创建了一个函数的副本。相反,我们可以传递一个箭头函数表达式,它简单地调用我们想要的函数,并保留this。您永远不需要在 React 中绑定 render 方法,但如果由于某种原因您在某个组件方法中丢失了 this

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}

【讨论】:

  • 你永远不需要绑定render(),因为它是由 React 调用的。如果有的话,您需要bind 事件处理程序,并且仅当您不使用箭头时。
  • 请注意,最好将props 传递给super()this.props 将在构造函数期间未定义,这可能会令人困惑。
  • 实现什么?您可以在功能组件内定义一个处理程序并传递它。每次渲染都会使用不同的函数,因此如果您使用分析器确定它会给您带来性能问题(并且只有当您确实确定这一点时!),请考虑改用类。
  • 谢谢艾克如。啊,好吧,所以你是说如果你将 foo 方法声明为类本身的箭头函数,然后使用 this 上下文引用它,然后它只创建一次,而不是在 onClick 中声明它,每次点击它都会创建相同的函数按钮。我的想法对吗?
  • @zuckerburg onClick={() => alert('hi')} 不会立即发出警报,onClick={this.showAlert} 也不会立即发出警报,因为在这两种情况下,您都在传递(而不是调用)a功能。
【解决方案3】:
class extends React.Component {
    onClickDiv = (column) => {
        // do stuff
    }
    render() {
        return <div onClick={() => this.onClickDiv('123')} />
    }
}

【讨论】:

  • 相同 - 每次渲染都有新的 DOM。所以 React 每次都会更新 DOM。
【解决方案4】:

另一个不涉及.bind 或 ES6 的选项是使用带有处理程序的子组件来调用具有必要道具的父处理程序。这是一个示例(下面是工作示例的链接):

var HeaderRows = React.createClass({
  handleSort:  function(value) {
     console.log(value);
  },
  render: function () {
      var that = this;
      return(
          <tr>
              {this.props.defaultColumns.map(function (column) {
                  return (
                      <TableHeader value={column} onClick={that.handleSort} >
                        {column}
                      </TableHeader>
                  );
              })}
              {this.props.externalColumns.map(function (column) {
                  // Multi dimension array - 0 is column name
                  var externalColumnName = column[0];
                  return ( <th>{externalColumnName}</th>
                  );
              })}
          </tr>);
      )
  }
});

// A child component to pass the props back to the parent handler
var TableHeader = React.createClass({
  propTypes: {
    value: React.PropTypes.string,
    onClick: React.PropTypes.func
  },
  render: function () {
    return (
      <th value={this.props.value} onClick={this._handleClick}
        {this.props.children}
      </th>
    )        
  },
  _handleClick: function () {
    if (this.props.onClick) {
      this.props.onClick(this.props.value);
    }
  }
});

基本思想是父组件将onClick函数传递给子组件。子组件调用onClick 函数并且可以访问传递给它的任何props(以及event),允许您在父onClick 函数中使用任何event 值或其他道具。

这是一个CodePen demo,展示了这个方法的实际应用。

【讨论】:

    【解决方案5】:

    [[@E.Sundin 在评论中回复linking this]

    最佳答案(匿名函数或绑定)会起作用,但它不是性能最高的,因为它会为map() 函数生成的每个实例创建事件处理程序的副本。

    这是来自ESLint-plugin-react的最佳方法的解释:

    物品清单

    在渲染中绑定的一个常见用例是在渲染列表时, 每个列表项一个单独的回调:

    const List = props => (
          <ul>
            {props.items.map(item =>
              <li key={item.id} onClick={() => console.log(item.id)}>
                ...
              </li>
            )}
          </ul>
        );
    

    不要这样做,而是将重复的部分拉到自己的 组件:

    const List = props => (
          <ul>
            {props.items.map(item =>
              <ListItem 
                key={item.id} 
                item={item} 
                onItemClick={props.onItemClick} // assume this is passed down to List
               />
            )}
          </ul>
        );
    
    
    const ListItem = props => {
      const _onClick = () => {
        console.log(props.item.id);
      }
        return (
          <li onClick={_onClick}>
            ...
          </li>
        );
    
    });
    

    这将加快渲染速度,因为它避免了创建新的 每次渲染上的函数(通过绑定调用)。

    【讨论】:

    • React 是否使用 call/apply 调用这些函数,然后,在幕后,并避免在内部使用绑定?
    • 有没有办法使用无状态组件来做到这一点?
    • @CarlosMartinez 好眼光,我更新了示例——它们本来应该是无状态功能组件 (SFC)。通常,如果某个组件从未使用过this.state,您可以安全地将其换成 SFC。
    • 嗯,我不明白这是如何提高性能的?不会每次都调用ListItem函数,所以每次渲染都会创建_onClick函数。
    • 我在这里远非专家,但据我了解,在“正确”模式中,只有一个处理程序实例,并且它传递了组件调用它的任何实例的 prop .在绑定示例(即“错误”模式)中,每个实例化组件都有一个处理程序实例。这相当于将相同的函数编写三十次,而不是编写一次并在需要时调用它。
    【解决方案6】:

    我认为,React 映射中的.bind(this, arg1, arg2, ...) - 是糟糕的代码,因为它很慢! 10-50 个 .bind(this) 采用单一渲染方法 - 非常慢的代码。
    我这样修复它:
    渲染方法
    &lt;tbody onClick={this.handleClickRow}&gt;
    &lt;tr data-id={listItem.id}&gt;的地图
    Handler
    var id = $(ev.target).closest('tr').data().id

    完整代码如下:

    class MyGrid extends React.Component {
      // In real, I get this from props setted by connect in Redux
      state = {
        list: [
          {id:1, name:'Mike'},
          {id:2, name:'Bob'},
          {id:3, name:'Fred'}
        ],
        selectedItemId: 3
      }
      
      render () {
        const { list, selectedItemId }  = this.state
        const { handleClickRow } = this
    
        return (
          <table>
            <tbody onClick={handleClickRow}>
              {list.map(listItem =>(
                <tr key={listItem.id} data-id={listItem.id} className={selectedItemId===listItem.id ? 'selected' : ''}>
                  <td>{listItem.id}</td>
                  <td>{listItem.name}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )
      }
      
      handleClickRow = (ev) => {
        const target = ev.target
        // You can use what you want to find TR with ID, I use jQuery
        const dataset = $(target).closest('tr').data()
        if (!dataset || !dataset.id) return
        this.setState({selectedItemId:+dataset.id})
        alert(dataset.id) // Have fun!
      }
    }
    
    ReactDOM.render(<MyGrid/>, document.getElementById("react-dom"))
    table {
      border-collapse: collapse;
    }
    
    .selected td {
      background-color: rgba(0, 0, 255, 0.3);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div id="react-dom"></div>

    【讨论】:

    • 请为你减去的内容写 cmets
    • 将 JQuery 与 React 混合不是使用 React 的推荐方式,尤其是在您对代码进行单元测试时。最惯用的答案是将列表项分成子组件,因为它们具有可能会影响应用程序状态的操作。
    • 我知道,但这只是为了最简单地演示我的解决方案。
    • 在您的代码中,jQuery 不仅仅是演示您的解决方案。对于&lt;tr&gt; 本身的处理程序,您可以省略closest 并且根本不需要jQuery,因此您的解决方案就像使用data-* 的其他解决方案一样。对于&lt;tr&gt; 内的组件上的处理程序,您需要一些 DOM 操作......正如已经说过的那样,这很糟糕,但没有要求这样的处理程序。
    • 你说得对。现在我认为,最好的方法是创建一个嵌套组件并从 map 函数中返回它。这样一来,您就无需使用 DOM,并且创建一个带有绑定的嵌套组件只需一次。
    【解决方案7】:

    这是我的做法,不知道有多差,请评论

    在可点击元素中

    return (
        <th value={column} onClick={that.handleSort} data-column={column}>   {column}</th>
    );
    

    然后

    handleSort(e){
        this.sortOn(e.currentTarget.getAttribute('data-column'));
    }
    

    【讨论】:

    • 这是我正在考虑的一种方法,感觉有点hacky,但避免创建新组件。与拉入单独的组件相比,我不确定 getAttribute 在性能方面是更好还是更差。
    • 我认为这是一个很好的解决方案,因为它非常简单。但它只适用于字符串值,如果你想要一个对象它不起作用。
    • 对于一个对象,您需要执行encodeURIComponent(JSON.stringify(myObj)),然后解析它,JSON.parse(decodeURIComponent(myObj))。对于函数,我很确定如果没有 eval 或 new Function(),这将无法工作,这两者都应该避免。由于这些原因,我不使用数据属性在 React/JS 中传递数据。
    • 我想补充一下,我不经常使用它,只用于小事。但通常我只是创建一个组件并将数据作为道具传递给它。然后要么处理该新组件内的点击,要么将 onClick 函数传递给组件。就像布兰登回答中解释的那样
    • 数据集在现代浏览器(包括IE11)上可以通过这种方式直接访问:e.currentTarget.dataset.column
    【解决方案8】:

    我对 JSX onClick 事件有以下 3 条建议 -

    1. 实际上,我们不需要在代码中使用 .bind() 或 Arrow 函数。您可以在代码中简单使用。

    2. 您还可以将 onClick 事件从 th(或 ul) 移动到 tr(或 li) 以提高性能。基本上,您的 n li 元素将拥有 n 个“事件侦听器”。

      So finally code will look like this:
      <ul onClick={this.onItemClick}>
          {this.props.items.map(item =>
                 <li key={item.id} data-itemid={item.id}>
                     ...
                 </li>
            )}
      </ul>
      

      // 并且可以在onItemClick方法中访问item.id,如下所示:

      onItemClick = (event) => {
         console.log(e.target.getAttribute("item.id"));
      }
      
    3. 我同意上面提到的为 ListItem 和 List 创建单独的 React 组件的方法。这使代码看起来不错,但是如果您有 1000 个 li,那么将创建 1000 个事件侦听器。请确保您不应该有太多的事件监听器。

      import React from "react";
      import ListItem from "./ListItem";
      export default class List extends React.Component {
      
          /**
          * This List react component is generic component which take props as list of items and also provide onlick
          * callback name handleItemClick
          * @param {String} item - item object passed to caller
          */
          handleItemClick = (item) => {
              if (this.props.onItemClick) {
                  this.props.onItemClick(item);
              }
          }
      
          /**
          * render method will take list of items as a props and include ListItem component
          * @returns {string} - return the list of items
          */
          render() {
              return (
                  <div>
                    {this.props.items.map(item =>
                        <ListItem key={item.id} item={item} onItemClick={this.handleItemClick}/>
                    )}
                  </div>
              );
          }
      
      }
      
      
      import React from "react";
      
      export default class ListItem extends React.Component {
          /**
          * This List react component is generic component which take props as item and also provide onlick
          * callback name handleItemClick
          * @param {String} item - item object passed to caller
          */
          handleItemClick = () => {
              if (this.props.item && this.props.onItemClick) {
                  this.props.onItemClick(this.props.item);
              }
          }
          /**
          * render method will take item as a props and print in li
          * @returns {string} - return the list of items
          */
          render() {
              return (
                  <li key={this.props.item.id} onClick={this.handleItemClick}>{this.props.item.text}</li>
              );
          }
      }
      

    【讨论】:

    • 当您需要传递的数据是一个对象时,这不起作用。该属性仅适用于字符串。此外,通过 get 属性从 dom 读取可能是更昂贵的操作。
    【解决方案9】:

    这里有很好的答案,我同意@Austin Greco(带有单独组件的第二个选项)
    我喜欢另一种方式,currying
    您可以做的是创建一个接受参数(您的参数)的函数并返回另一个接受另一个参数的函数(在本例中为 click 事件)。那么你就可以随心所欲地使用它了。

    ES5:

    handleChange(param) { // param is the argument you passed to the function
        return function (e) { // e is the event object that returned
    
        };
    }
    

    ES6:

    handleChange = param => e => {
        // param is the argument you passed to the function
        // e is the event object that returned
    };
    

    你会这样使用它:

    <input 
        type="text" 
        onChange={this.handleChange(someParam)} 
    />
    

    以下是此类用法的完整示例:

    const someArr = ["A", "B", "C", "D"];
    
    class App extends React.Component {
      state = {
        valueA: "",
        valueB: "some initial value",
        valueC: "",
        valueD: "blah blah"
      };
    
      handleChange = param => e => {
        const nextValue = e.target.value;
        this.setState({ ["value" + param]: nextValue });
      };
    
      render() {
        return (
          <div>
            {someArr.map(obj => {
              return (
                <div>
                  <label>
                    {`input ${obj}   `}
                  </label>
                  <input
                    type="text"
                    value={this.state["value" + obj]}
                    onChange={this.handleChange(obj)}
                  />
                  <br />
                  <br />
                </div>
              );
            })}
          </div>
        );
      }
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    请注意,这种方法不能解决在每次渲染时创建新实例的问题。
    与其他内联处理程序相比,我更喜欢这种方法,因为我认为这种方法更简洁易读。

    编辑:
    正如下面的 cmets 中所建议的,您可以缓存/记忆函数的结果。

    这是一个简单的实现:

    let memo = {};
    
    const someArr = ["A", "B", "C", "D"];
    
    class App extends React.Component {
      state = {
        valueA: "",
        valueB: "some initial value",
        valueC: "",
        valueD: "blah blah"
      };
    
      handleChange = param => {
        const handler = e => {
          const nextValue = e.target.value;
          this.setState({ ["value" + param]: nextValue });
        }
        if (!memo[param]) {
          memo[param] = e => handler(e)
        }
        return memo[param]
      };
    
      render() {
        return (
          <div>
            {someArr.map(obj => {
              return (
                <div key={obj}>
                  <label>
                    {`input ${obj}   `}
                  </label>
                  <input
                    type="text"
                    value={this.state["value" + obj]}
                    onChange={this.handleChange(obj)}
                  />
                  <br />
                  <br />
                </div>
              );
            })}
          </div>
        );
      }
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root" />

    【讨论】:

    • 这应该是公认的答案。真的很容易实现,你不需要创建任何其他组件或以不同的方式绑定。谢谢!
    • 看起来更好,但是从性能的角度来看,currying 并没有真正的帮助,因为如果你使用相同的参数调用两次 handleChange,你会得到两个 JS 引擎认为是独立对象的函数,即使他们做同样的事情。所以你仍然得到重新渲染。为了性能,您需要缓存 handleChange 的结果以获得性能优势。喜欢handleChange = param =&gt; cache[param] || (e =&gt; { // the function body })
    • 如果您满足@travellingprog 的建议,这是完美的答案
    • 谁能提供一个链接或解释这个缓存机制是如何工作的?谢谢。
    • 如果使用柯里化,每次渲染都会创建新函数。与传递箭头函数相同的性能问题。
    【解决方案10】:

    此示例可能与您的示例略有不同。但我可以向您保证,这是您可以解决此问题的最佳解决方案。 我已经寻找了几天没有性能问题的解决方案。终于想出了这个。

    class HtmlComponent extends React.Component {
      constructor() {
        super();
        this.state={
           name:'MrRehman',
        };
        this.handleClick= this.handleClick.bind(this);
      }
    
      handleClick(event) {
        const { param } = e.target.dataset;
        console.log(param);
        //do what you want to do with the parameter
      }
    
      render() {
        return (
          <div>
            <h3 data-param="value what you wanted to pass" onClick={this.handleClick}>
              {this.state.name}
            </h3>
          </div>
        );
      }
    }
    

    更新

    如果您想处理应该是参数的对象。您可以使用JSON.stringify(object) 将其转换为字符串并添加到数据集中。

    return (
       <div>
         <h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
            {this.state.name}
         </h3>
       </div>
    );
    

    【讨论】:

    • 这在传递的数据是对象时不起作用
    • 使用 JSON.stringify 解决问题。 @SlimSim。这应该可以解决问题
    • 如果你需要使用 JSON.stringify 来解决这个问题,那么它可能不是正确的方法。字符串化的过程会占用大量内存。
    • 在大多数情况下,您只会将 ID 作为参数传递,并根据该 ID 从源对象中获取对象详细信息。以及为什么以及如何占用大量内存,我知道 JSON stringify 很慢,但是单击 Fn 是异步的,一旦构建,它将对 dom 没有影响或影响为 0
    【解决方案11】:

    我编写了一个包装器组件,可以在此目的上重复使用,它建立在此处接受的答案的基础上。但是,如果您需要做的只是传递一个字符串,那么只需添加一个数据属性并从 e.target.dataset 读取它(就像其他一些人建议的那样)。默认情况下,我的包装器将绑定到任何作为函数并以“on”开头的道具,并在所有其他事件参数之后自动将数据道具传递回调用者。虽然我没有测试过它的性能,但它会让你有机会避免自己创建类,它可以这样使用:

    const DataButton = withData('button')

    const DataInput = withData('input');

    或用于组件和功能

    const DataInput = withData(SomeComponent);

    或者如果你喜欢

    const DataButton = withData(&lt;button/&gt;)

    声明在您的容器外(靠近您的进口)

    这是容器中的用法:

    import withData from './withData';
    const DataInput = withData('input');
    
    export default class Container extends Component {
        state = {
             data: [
                 // ...
             ]
        }
    
        handleItemChange = (e, data) => {
            // here the data is available 
            // ....
        }
    
        render () {
            return (
                <div>
                    {
                        this.state.data.map((item, index) => (
                            <div key={index}>
                                <DataInput data={item} onChange={this.handleItemChange} value={item.value}/>
                            </div>
                        ))
                    }
                </div>
            );
        }
    }
    

    这里是包装代码'withData.js:

    import React, { Component } from 'react';
    
    const defaultOptions = {
        events: undefined,
    }
    
    export default (Target, options) => {
        Target = React.isValidElement(Target) ? Target.type : Target;
        options = { ...defaultOptions, ...options }
    
        class WithData extends Component {
            constructor(props, context){
                super(props, context);
                this.handlers = getHandlers(options.events, this);        
            }
    
            render() {
                const { data, children, ...props } = this.props;
                return <Target {...props} {...this.handlers} >{children}</Target>;
            }
    
            static displayName = `withData(${Target.displayName || Target.name || 'Component'})`
        }
    
        return WithData;
    }
    
    function getHandlers(events, thisContext) {
        if(!events)
            events = Object.keys(thisContext.props).filter(prop => prop.startsWith('on') && typeof thisContext.props[prop] === 'function')
        else if (typeof events === 'string')
            events = [events];
    
        return events.reduce((result, eventType) => {
            result[eventType] = (...args) => thisContext.props[eventType](...args, thisContext.props.data);
            return result;
        }, {});
    }
    

    【讨论】:

      【解决方案12】:

      我添加了 onclick 事件值以两种方式传递给方法的代码。 1.使用绑定方法 2. 使用箭头(=>)方法。查看方法 handlesort1 和 handlesort

      var HeaderRows  = React.createClass({
          getInitialState : function() {
            return ({
              defaultColumns : ["col1","col2","col2","col3","col4","col5" ],
              externalColumns : ["ecol1","ecol2","ecol2","ecol3","ecol4","ecol5" ],
      
            })
          },
          handleSort:  function(column,that) {
             console.log(column);
             alert(""+JSON.stringify(column));
          },
          handleSort1:  function(column) {
             console.log(column);
             alert(""+JSON.stringify(column));
          },
          render: function () {
              var that = this;
              return(
              <div>
                  <div>Using bind method</div>
                  {this.state.defaultColumns.map(function (column) {
                      return (
                          <div value={column} style={{height : '40' }}onClick={that.handleSort.bind(that,column)} >{column}</div>
                      );
                  })}
                  <div>Using Arrow method</div>
      
                  {this.state.defaultColumns.map(function (column) {
                      return (
                          <div value={column} style={{height : 40}} onClick={() => that.handleSort1(column)} >{column}</div>
      
                      );
                  })}
                  {this.state.externalColumns.map(function (column) {
                      // Multi dimension array - 0 is column name
                      var externalColumnName = column;
                      return (<div><span>{externalColumnName}</span></div>
                      );
                  })}
      
              </div>);
          }
      });
      

      【讨论】:

        【解决方案13】:

        替代尝试回答 OP 的问题,包括 e.preventDefault() 调用:

        渲染链接(ES6

        <a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>
        

        组件功能

        handleSort = (e, param) => {
          e.preventDefault();
          console.log('Sorting by: ' + param)
        }
        

        【讨论】:

          【解决方案14】:

          使用箭头函数:

          您必须安装第 2 阶段:

          npm install babel-preset-stage-2 :

          class App extends React.Component {
              constructor(props) {
                  super(props);
                  this.state = {
                      value=0
                  }
              }
          
              changeValue = (data) => (e) => {
                  alert(data);  //10
                  this.setState({ [value]: data })
              }
          
              render() {
                  const data = 10;
                  return (
                      <div>
                          <input type="button" onClick={this.changeValue(data)} />
                      </div>
                  );
              }
          }
          export default App; 
          

          【讨论】:

            【解决方案15】:

            有 3 种方法可以解决这个问题:-

            1. 将构造函数中的方法绑定为:-

              export class HeaderRows extends Component {
                 constructor() {
                     super();
                     this.handleSort = this.handleSort.bind(this);
                 }
              }
              
            2. 在创建时使用箭头函数:-

              handleSort = () => {
                  // some text here
              }
              
            3. 第三种方法是这样的:-

              <th value={column} onClick={() => that.handleSort} >{column}</th>
              

            【讨论】:

              【解决方案16】:

              如果你使用ES6,你可以简单地做到这一点。

              export default class Container extends Component {
                state = {
                  data: [
                      // ...
                  ]
                }
              
                handleItemChange = (e, data) => {
                    // here the data is available 
                    // ....
                }
                render () {
                   return (
                      <div>
                      {
                         this.state.data.map((item, index) => (
                            <div key={index}>
                                <Input onChange={(event) => this.handItemChange(event, 
                                       item)} value={item.value}/>
                            </div>
                         ))
                      }
                      </div>
                   );
                 }
               }
              

              【讨论】:

                【解决方案17】:

                通过将计数作为参数从主组件传递到子组件来实现显示对象的总计数,如下所述。

                这里是 MainComponent.js

                import React, { Component } from "react";
                
                import SubComp from "./subcomponent";
                
                class App extends Component {
                
                  getTotalCount = (count) => {
                    this.setState({
                      total: this.state.total + count
                    })
                  };
                
                  state = {
                    total: 0
                  };
                
                  render() {
                    const someData = [
                      { name: "one", count: 200 },
                      { name: "two", count: 100 },
                      { name: "three", count: 50 }
                    ];
                    return (
                      <div className="App">
                        {someData.map((nameAndCount, i) => {
                          return (
                            <SubComp
                              getTotal={this.getTotalCount}
                              name={nameAndCount.name}
                              count={nameAndCount.count}
                              key={i}
                            />
                          );
                        })}
                        <h1>Total Count: {this.state.total}</h1>
                      </div>
                    );
                  }
                }
                
                export default App;
                

                这里是SubComp.js

                import React, { Component } from 'react';
                export default class SubComp extends Component {
                
                  calculateTotal = () =>{
                    this.props.getTotal(this.props.count);
                  }
                
                  render() {
                    return (
                      <div>
                        <p onClick={this.calculateTotal}> Name: {this.props.name} || Count: {this.props.count}</p>
                      </div>
                    )
                  }
                };
                

                尝试在上面实现,您将获得传递参数如何在任何 DOM 方法上的 reactjs 中工作的确切场景。

                【讨论】:

                  【解决方案18】:

                  以下是在 onClick 事件上传递值的示例。

                  我使用的是 es6 语法。记住在类组件中箭头函数不会自动绑定,所以在构造函数中显式绑定。

                  class HeaderRows extends React.Component {
                  
                      constructor(props) {
                          super(props);
                          this.handleSort = this.handleSort.bind(this);
                      }
                  
                      handleSort(value) {
                          console.log(value);
                      }
                  
                      render() {
                          return(
                              <tr>
                                  {this.props.defaultColumns.map( (column, index) =>
                                      <th value={ column } 
                                          key={ index } 
                                          onClick={ () => this.handleSort(event.target.value) }>
                                          { column }
                                      </th>
                                  )}
                  
                                  {this.props.externalColumns.map((column, index)  =>
                                      <th value ={ column[0] }
                                          key={ index }>
                                          {column[0]}
                                      </th>
                                  )}
                              </tr>
                           );
                      }
                  }
                  

                  【讨论】:

                    【解决方案19】:

                    我猜你必须将方法绑定到 React 的类实例。使用构造函数绑定 React 中的所有方法更安全。在您将参数传递给方法时,第一个参数用于绑定方法的“this”上下文,因此您无法访问方法内部的值。

                    【讨论】:

                      【解决方案20】:
                      1. You just have to use an arrow function in the Onclick event like this: 
                      
                      <th value={column} onClick={() => that.handleSort(theValue)} >{column}</th>
                      
                      2.Then bind this in the constructor method:
                          this.handleSort = this.handleSort.bind(this);
                      
                      3.And finally get the value in the function:
                        handleSort(theValue){
                           console.log(theValue);
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        有一个非常简单的方法。

                         onClick={this.toggleStart('xyz')} . 
                          toggleStart= (data) => (e) =>{
                             console.log('value is'+data);  
                         }
                        

                        【讨论】:

                          【解决方案22】:

                          我意识到这对聚会来说已经很晚了,但我认为一个更简单的解决方案可以满足许多用例:

                              handleEdit(event) {
                                  let value = event.target.value;
                              }
                          
                              ...
                          
                              <button
                                  value={post.id}
                                  onClick={this.handleEdit} >Edit</button>
                          

                          我想你也可以使用data- 属性。

                          简单,语义化。

                          【讨论】:

                            【解决方案23】:
                            class TableHeader extends Component {
                              handleClick = (parameter,event) => {
                            console.log(parameter)
                            console.log(event)
                            
                              }
                            
                              render() {
                                return (
                                  <button type="button" 
                            onClick={this.handleClick.bind(this,"dataOne")}>Send</button>
                                );
                              }
                            }
                            

                            【讨论】:

                            • 虽然这段代码可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
                            【解决方案24】:

                            您可以像这样使用您的代码:

                            <th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>
                            

                            这里的 e 是事件对象,如果你想在你的句柄函数中使用像 preventDefault() 这样的事件方法,或者想要获得像 e.target.name 这样的目标值或名称。

                            【讨论】:

                              【解决方案25】:

                              有几种方法可以在事件处理程序中传递参数,如下所示。

                              您可以使用箭头函数来包裹事件处理程序并传递参数:

                              <button onClick={() => this.handleClick(id)} />
                              

                              上面的例子等价于调用.bind或者你可以显式调用bind。

                              <button onClick={this.handleClick.bind(this, id)} />
                              

                              除了这两种方法之外,您还可以将参数传递给定义为 curry 函数的函数。

                              handleClick = (id) => () => {
                                  console.log("Hello, your ticket number is", id)
                              };
                              
                              <button onClick={this.handleClick(id)} />
                              

                              【讨论】:

                                【解决方案26】:

                                突然冒出这个问题,但我认为.bind 可以解决问题。找到下面的示例代码。

                                const handleClick = (data) => {
                                    console.log(data)
                                }
                                
                                <button onClick={handleClick.bind(null, { title: 'mytitle', id: '12345' })}>Login</button>
                                

                                【讨论】:

                                  【解决方案27】:

                                  有很多性能方面的考虑,都在真空中。
                                  此处理程序的问题是您需要对它们进行 curry,以便将您无法在 props 中命名的参数合并。
                                  这意味着该组件需要一个处理程序来处理每个可点击元素。让我们同意,对于几个按钮来说,这不是问题,对吧?
                                  当您处理具有数十列和数千行的表格数据时,就会出现问题。在那里,您会注意到创建这么多处理程序的影响。

                                  事实上,我只需要一个。
                                  我将处理程序设置在表级别(或 UL 或 OL ...),当点击发生时,我可以使用事件对象中的可用数据来判断哪个是点击的单元格:

                                  nativeEvent.target.tagName
                                  nativeEvent.target.parentElement.tagName 
                                  nativeEvent.target.parentElement.rowIndex
                                  nativeEvent.target.cellIndex
                                  nativeEvent.target.textContent
                                  

                                  我使用标记名字段来检查点击是否发生在有效元素中,例如忽略在 TH 或页脚中的点击。
                                  rowIndex 和 cellIndex 给出了被点击单元格的确切位置。
                                  Textcontent 是单击单元格的文本。

                                  这样我不需要将单元格的数据传递给处理程序,它可以自助服务。
                                  如果我需要更多数据、不显示的数据,我可以使用数据集属性或隐藏元素。
                                  通过一些简单的 DOM 导航,一切尽在掌握。
                                  从那时起,这一直在 HTML 中使用,因为 PC 更容易陷入困境。

                                  【讨论】:

                                  • 你提出了一个非常重要的问题——性能考虑!
                                  【解决方案28】:

                                  需要简单修改:

                                  使用 &lt;th value={column} onClick={that.handleSort} &gt;{column}&lt;/th&gt;

                                  而不是 &lt;th value={column} onClick={that.handleSort} &gt;{column}&lt;/th&gt;

                                  【讨论】:

                                    【解决方案29】:

                                    像这样简单地创建一个函数

                                      function methodName(params) {
                                        //the thing  you wanna do
                                      }
                                    

                                    在你需要的地方调用它

                                     <Icon onClick = {() => { methodName(theParamsYouwantToPass);} }/>
                                    

                                    【讨论】:

                                    • Oc ??????
                                    • 哈哈哈,这很有效!你甚至不需要花括号和括号。有谁知道这里的 React 是如何处理匿名函数的?
                                    【解决方案30】:

                                    您只需要使用箭头函数来传递值。

                                    &lt;button onClick={() =&gt; this.props.onClickHandle("StackOverFlow")}&gt;

                                    一定要使用()=>,否则会在没有点击事件的情况下调用点击方法。

                                    注意:崩溃检查默认方法

                                    请在下面的代码和框中找到相同的运行代码。

                                    React pass value with method

                                    【讨论】:

                                      猜你喜欢
                                      • 2020-08-03
                                      • 1970-01-01
                                      • 2011-12-07
                                      • 2016-11-01
                                      • 2021-06-02
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多