React.js Serverside渲染和事件处理程序

时间:2016-03-26 08:42:31

标签: javascript node.js reactjs event-handling

我正在学习使用react.js并使用事件处理程序时遇到一些问题。最后一个问题是:是否可以使用服务器端呈现并自动向客户端发送事件处理程序?

这是我的例子: 我有一个index.jsx,我渲染服务器端并发送到客户端

var React = require("react");
var DefaultLayout = require("./layout/default");

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false}; 
  }, 
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  }, 
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  } 
});

var IndexComponent = React.createClass({
   render: function(){
       return (
           <DefaultLayout title={this.props.name}>
                <div>
                        <h1>React Test</h1>
                </div>

                <div id="testButton">
                    <LikeButton/>
                </div> 

                <script type="text/babel" src="/js/react.js"></script>
           </DefaultLayout>
       )
   }   
});

但是“Like Button”没有任何互动。要使它在点击时执行某些操作,我必须添加此代码客户端。

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('testButton')
);

我只是从react.js开始,也许我只是缺少一些主要的概念。但是为什么react.js不仅仅是在渲染页面服务器端时创建代码(我现在必须手动添加到客户端)? 像这样,我有冗余的代码,感觉这在大型应用程序中会变得混乱。 至少react.js足够聪明,不能绘制两个LikeButtons,而是将创建的服务器端“绑定”到客户端组件。

2 个答案:

答案 0 :(得分:30)

此行为是因为服务器端呈现的确切原因。 首先,您必须在客户端和服务器端运行完全相同的代码。这就是所谓的同构应用程序。一个在服务器和客户端上运行的 因此,在执行ReactDOM.renderToString(<Component>)时,只将HTML呈现为字符串。将评估组件的render方法,并生成初始渲染所需的HTML 当在客户端上运行相同的代码时,react会查找呈现的HTML并在需要的位置附加JS。 React以这种方式很聪明,它不会在客户端再次重新渲染所有内容。只需评估代码并确定基于react-id每个DOM元素的所有附加代码的位置。 (如果你检查任何反应应用程序的元素,你会发生反应)

现在有人可能会问两次渲染相同的东西有什么好处? 并且用户的答案是perceived loading time。对于禁用JS的用户,还有一些最小的查看。

客户端呈现的应用
这是单独客户端呈现的应用程序的工作方式。 (客户端也提供了React应用程序)

client rendered app

用户只会在所有骨架HTML,JS捆绑(通常非常大)之后看到内容,并且会获取和评估数据。这意味着用户通常必须盯着微调器或加载屏幕一段时间,直到所有加载。

同构应用程序(在客户端和服务器上运行)
同构应用程序如何工作,
server rendered app
在这种情况下,服务器通过评估您的组件来生成完整 HTML。一旦下载HTML,用户就会立即看到内容。 虽然只有在下载和评估JS捆绑包后,应用程序才能完全运行。所以JS必须在双方运行 因此,用户比以前更快地看到内容。因此,感知加载时间大幅减少。

答案 1 :(得分:17)

对于客户端交互式React应用程序,您还需要呈现应用程序客户端。通常此代码与您在服务器上运行的代码相同,因此没有冗余代码。它只是相同的代码。您可能会问自己,客户端和服务器上的渲染是否过度,但从性能和搜索引擎优化的角度来看,它是完全合理的。

ReactDOMServer.renderToString(<MyApp foo={bar} />)基本上只是呈现带有标记的字符串。那里没有javascript或任何魔法。只是简单的旧HTML。但是,呈现的标记具有许多React ID属性,这些属性稍后在客户端上用于生成初始Virtual DOM和附加事件。

当您在客户端上再次呈现应用程序时,在服务器上注入服务器端呈现标记的同一DOM元素上,React不需要重绘整个应用程序。它只是创建一个新的Virtual DOM树,使用初始Virtual DOM树对其进行区分,并执行必要的DOM操作(如果有的话)。虚拟DOM的这个概念首先使React变得如此之快。在同一个过程中,您在应用程序中定义的任何事件侦听器都将附加到已渲染的标记。

所有这一切都发生得非常快。您可以利用服务器端呈现的页面(可以在服务器上缓存,使用Varnish或类似的东西)搜索引擎将抓取,用户不需要等待任何事情来查看初始渲染,以及该页面主要适用于已禁用javascript的用户。

相关问题