React.js 服务器端渲染和事件处理程序

IT技术 javascript node.js reactjs event-handling
2021-03-01 03:39:04

我正在学习使用 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>
       )
   }   
});

但是“赞按钮”没有任何交互。为了让它在点击时做一些事情,我必须添加这个代码客户端。

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 足够聪明,不会绘制两个 LikeButton,而是将创建的服务器端“绑定”到客户端组件。

2个回答

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

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

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

客户端呈现的应用程序

用户只会在所有框架 HTML、JS 包(通常非常大)以及数据被获取和评估后才能看到内容。这意味着用户通常不得不盯着微调器或加载屏幕一段时间,直到一切都加载完毕。

同构应用程序(在客户端和服务器上运行)
同构应用程序的工作原理, 在这种情况下,服务器通过评估您的组件生成完整的HTML。下载 HTML 后,用户将立即看到内容。尽管该应用程序只有在 JS 包也被下载和评估后才能完全运行所以JS必须在两边运行, 因此用户看到内容的速度比以前快得多。因此,感知加载时间大幅减少。
服务器渲染的应用程序

我确实将@dannyjolie 的答案标记为正确,因为它回答了我的问题并且较早发布。但仍然非常感谢您为回答我的问题所做的努力。它还帮助我更好地了解 react.js 的工作原理及其遵循的概念!
2021-05-05 03:39:04

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

ReactDOMServer.renderToString(<MyApp foo={bar} />)基本上只是渲染一个带有标记的字符串。那里没有 javascript 或任何魔法。只是普通的旧 HTML。然而,渲染的标记有很多 React ID 属性,稍后会在客户端使用这些属性来生成初始虚拟 DOM 和附加事件。

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

所有这一切都发生得非常快。并且你有一个服务器端呈现的页面(可以缓存在服务器上,使用 Varnish 或类似的东西)的好处,搜索引擎将抓取它,用户不需要等待任何东西来查看初始呈现,以及页面基本上适用于禁用 javascript 的用户。

感谢您的回答。你知道使用 React 和 Varnish 的好文章吗?
2021-05-05 03:39:04