内部和外部的函数render()

时间:2018-04-02 17:46:34

标签: javascript reactjs

我刚刚开始学习React和JavaScript。在我阅读了文档和教程之后,我看了一些示例项目,并尝试找出我还没有得到的内容。

然后我看到有render()函数内部定义的函数,以及render()函数之外的函数。

E.g。在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()中使用函数呢?

3 个答案:

答案 0 :(得分:2)

来自official site:

的示例

首先,如果我们想在开始时构建一个Clock,那么我们就尝试使用无状态函数对象创建一个面向对象,可维护的组件。

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

引自doc

  

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

     

...   理想情况下,我们想要写一次并自己更新时钟......

所以这里是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();
     }
}

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

<强>更新

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

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

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

我认为这样做的原因只是为了可维护性,有人可能希望所有DOM在render()内部创建代码,以便在返回的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操作功能的功能是完全正确的,并且可以在外部定义。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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