【问题标题】:Functions inside and outside render()render() 内部和外部的函数
【发布时间】:2018-09-11 22:53:10
【问题描述】:

我刚开始学习 React 和 JavaScript。阅读文档和教程后,我查看了示例项目并尝试整理出我还没有得到的东西。

然后我看到render()functions 内部定义了一些函数,render() 函数外部定义了一些函数。

例如对于render()之外的:

handleClick(e) {
    e.preventDefault();
    e.target.parentElement.classList.toggle('open');
  }

在 render() 内部...

const divider = (divider, key) => {
      const classes = classNames( 'divider', divider.class);
      return (<li key={key} className={ classes }></li>);
    };

为什么它们看起来如此不同,为什么您希望在render() 内部和外部拥有一些功能?

编辑:

render() 之外的另一个函数示例:

hideMobile() {
    if (document.body.classList.contains('sidebar-mobile-show')) {
      document.body.classList.toggle('sidebar-mobile-show')
    }
  }

EDIT2:在另一个线程中,有人回答说,如果函数背后的逻辑很重,它应该在 render() 之外。但是你为什么还要在 render() 里面有函数呢?

【问题讨论】:

  • 据我所知,render() 中的所有内容都是不断循环的。
  • @ionizer 好吧,我知道,但你为什么要在连续循环的函数中使用函数呢?
  • divider 称为 lambda 函数或匿名函数。有时,您希望它只定义和使用一次函数。在这种情况下,我相信您可以将 divider 移到 render() 函数之外,因为它不引用任何外部范围变量。
  • @Goldi 是的,这对我来说可能是主要的原因。

标签: javascript reactjs


【解决方案1】:

除此之外,handleClick 是为每个对象/组件创建和访问的函数,divide 是本地范围的函数,它们的功能几乎相同。但是,divider 将在每次渲染时创建为新函数,这可能会对以后的性能产生影响,而 handleClick 会为已定义的组件(对象)创建一次。

【讨论】:

  • 嗯,我已经知道你描述的行为,只是我不知道你为什么要这样。在不知道“为什么”的情况下,我会假设将函数放在 render() 函数中总是不好的,因为 render 会不断被调用,因此 render() 中的函数将不断重新定义
  • @Goldi render will be called constantly - 不,为什么?仅当您将该函数作为 prop 传递时,子组件才会始终获得一个新函数 - 实际上它并没有改变。
  • 对不起,这就是我所说的不断。我是说你描述的。 (我实际上的意思是持续)
【解决方案2】:

render() 每次state 更改时都会被调用。因此,每次 state 更改时,保存在 render 函数中的每个函数都将创建为一个新函数。这意味着每次 react 重新渲染时都会新创建 divider

handleClick 是一个普通的对象函数。

render 函数中编写的函数通常是那些处理组件重新渲染的函数。

【讨论】:

  • props 改变时不会被调用。
【解决方案3】:

来自official site:上的示例

首先,如果我们想在开始时构建一个时钟,我们尝试使用无状态函数对象来制作一个面向对象、可维护因素的组件。

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
   ReactDOM.render(
     <Clock date={new Date()} />,
     document.getElementById('root')
   );
}

setInterval(tick, 1000);

引用自文档

使时钟组件真正可重用和封装。它会 设置自己的计时器并每秒更新一次。

... 理想情况下,我们希望编写一次并让时钟自行更新......

所以这就是React的精神,我们想把这个函数对象转换成一个类,它可以自己维护,所以现在我们涉及到render(),更具体地说我们涉及到有状态组件

Add a single empty method to it called render()
...
Clock is now defined as a class rather than a function.

然后我们得到:

class Clock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {date: new Date()};
        this.clockCore = this.clockCore.bind(this);
    }

    componentDidMount() {
        this.timerID = setInterval(
          () => this.tick(),
           1000
        );
     }

     tick() {
         this.setState({
             date: new Date()
         });
     }

     clockCore() {
         return (<div>
            <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
         </div>);
     }

     render() {
        return this.clockCore();
     }
}

如您所知,如果组件的状态需要由setState() 刷新,则render() 会再次触发。


更新

在我看来,没有必要在render() 中定义函数。 我对上面的原始示例进行了一些修改以表明这一点。

从您提供的示例中,分隔符的用法可能如下:

const divider = (divider, key) => {
  const classes = classNames( 'divider', divider.class);
  return (<li key={key} className={ classes }></li>);
};

return (<ul>{this.state.dividerList?
    this.state.dividerList.forEach(divider) : null}</ul>);

我认为这样做的原因只是为了可维护性,有人可能希望在 render() 中创建所有 DOM 代码,以便在返回的 DOM 结构非常复杂(和 arrow function is lightweight)时轻松跟踪,但正如我所说,这是主观的,它真的可以在外面定义。

在这种情况下,我曾经在下面做,看起来你提供的更优雅,但如果你在render()之外定义了那个函数,事情就会分散我的注意力.

let dividers = [];
if (this.state.dividerList) {
    this.state.dividerList.forEach((divider, key) => {
        let classes = classNames( 'divider', divider.class);
        dividers.push((<li key={key} className={ classes }></li>));
    });
}

return (<ul>{dividers}</ul>);

因此,您提供的另一个针对 DOM 操作功能的功能是完全合适的,可以在外部定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-23
    • 2012-08-25
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多