【问题标题】:Why can't I use "this" in a JSX rendered html element?为什么我不能在 JSX 呈现的 html 元素中使用“this”?
【发布时间】:2017-08-08 13:33:00
【问题描述】:

我的问题是关于在 JSX 中进行条件渲染和this 的使用。

在我的 React 应用程序中考虑以下代码:

render() {
    return (
        <li onMouseEnter={this.mouseEnter}>
          //things
        </li>
      )
    }

我想有条件地渲染onMouseEnter 属性,这样它就不会在每次组件被调用并显示&lt;li&gt; 标记时应用。

例如:

render() {
    return (
        <li {this.renderMouseEvents()} >
          ...
        </li>
      )
    }

但 Visual Studio 抱怨说“[js] “...”是预期的”

显然在 HTML 元素之外调用 { this.renderMouseEvents() } 接受使用 this

为什么this 在 JSX 的 html 元素中无效?

在 JSX 中完成这种条件渲染的正确/更简洁的方法是什么?

感谢任何帮助,谢谢!

【问题讨论】:

  • 为什么不简单地在 mouseEnter 函数中添加条件?
  • 这个问题提出了一个XY problem。您的 JSX sn-p 在语法上无效,但 this 的用法与它无关。

标签: javascript reactjs jsx


【解决方案1】:

只需将条件插入到属性中:

import noop from 'lodash/noop';

render() {
    return (
        <li onMouseEnter={ifSatisfies ? this.mouseEnter : noop}>
          //things
        </li>
      )
    }

【讨论】:

    【解决方案2】:

    你写的不是有效的 JSX 语法。请尝试以下方法:

    mouseEnterBehaviorEnabled() 是一个返回truefalse 的函数。在这里,您可以设置您希望何时触发 mouseEnter 的逻辑。

    看看 MDN 上的Short circuit evaluation

    render() {
      return (
        <li onMouseEnter={this.mouseEnterBehaviorEnabled() && this.mouseEnter} >
          ...
        </li>
      );
    }
    

    你当然也可以这样做

    render() {
      return (
        <li onMouseEnter={this.mouseEnter} >
          ...
        </li>
      );
    }
    

    并在原始行为的其余部分之前在 mouseEnter 中运行您的逻辑。如果这些条件失败,则返回 false,其余的将不会被执行。

    【讨论】:

    • 当表达式被评估为假时会发生什么? onMouseEnter 属性是简单地被 react 忽略,还是被渲染为 onMouseEnter={}
    • 我相信您将语法与传统的内联 HTML 事件处理程序混淆了。如果您检查您的代码,则没有onMouseEnter“属性”并且它们不会被渲染。但长话短说;因为mouseEnterBehaviorEnabled()false 表达式this.mouseEnterBehaviorEnabled() &amp;&amp; this.mouseEnter 也是假的,这意味着onMouseEnter 也是假的——所以,什么都不会发生。
    • 有道理。感谢您的反馈/信息!
    • 请记住,您的方法不能正确使用 PropTypes,因为此 this.mouseEnterBehaviorEnabled() &amp;&amp; this.mouseEnter 返回一个布尔值,onMouseEnterPropTypes.func 定义将为提供的错误类型的 prop 引发错误.因此,为什么在条件为 false 时应该传入一个空函数(noop 方法,f.e.)。
    • @Denialos 我想我明白你来自哪里,但我相信你的建议是错误的。仅当道具被定义为必需(例如myFunc: PropTypes.func.isRequired)时才会出现问题。您指的是标准鼠标事件onMouseEnter,这不是必需的道具。因此,传递nullfalseundefined 等是完全有效的。
    【解决方案3】:

    您可以通过使用扩展运算符 (ES6) 和逻辑 AND 短路评估来做到这一点:

    ...{ onClick: condition && this.handleClick }
    

    示例:

    const arr = ["1", "2", "3"];
    
    class App extends React.Component {
      constructor(props) {
        super(props);
      }
    
      handleClick = e => {
        console.log(e.target.innerHTML);
      };
    
      render() {
        return (
          <div>
            {arr.map(o => {
              const myProps = {
                ...{ onClick: o != "1" && this.handleClick }
              };
              return (
                <li {...myProps}>
                  {o}
                </li>
              );
            })}
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <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>

    【讨论】:

      【解决方案4】:

      你可以在 JSX 中使用this,我认为这不是问题。

      如果this是问题所在,可能是在你的方法renderMouseEvents里面,你是不是把bind改成this了?

      但我认为它不起作用,因为您的方法 renderMouseEvents 正在返回。虽然可以注入属性,但请检查一下,它可能会有所帮助:

      Dynamic attribute in ReactJS

      【讨论】:

      • 不,他只是不能在类似jsx html的TAG中插入JS
      • 在我发布的链接中,它似乎有效:return &lt;button {...opts}&gt;Hello {this.props.name}&lt;/button&gt;; 按钮是一个 HTML 标签,它接收一些可以通过方法返回的道具,不是吗?我以前做过,效果很好。
      【解决方案5】:

      如果我理解您的问题,我相信您遇到的问题必须处理 JSX 如何转换为 JavaScript。

      <el arg1="1" arg2="2">3</el>
      

      被翻译成类似于以下内容:

      React.createElement('el', { arg1: '1', arg2: '2' }, '3');
      

      假设您的renderMouseEvents() 返回{ onMouseEnter: this.mouseEnter },您所写的内容可能会尝试这样翻译:

      React.createElement('li', { { onMouseEnter: this.mouseEnter } }, '...');
      

      这是无效的 JavaScript。编译器告诉您它期待 ...(JavaScript 传播语法),这可能会解决此问题。

      正如 noppa 所说,可能有更好的方法来实现您想要的。您能否更具体地说明您面临的问题?

      【讨论】:

        猜你喜欢
        • 2013-12-09
        • 1970-01-01
        • 2021-01-29
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多