0

与客户端渲染相比,我更喜欢对用户交互很少的应用程序使用服务器端渲染。而 webpack 是编译服务器端代码的选择。

有一个场景我想在组件渲染后更新表格的marginTop 。如果是客户端渲染,会列出如下实现

componentDidMount() {
  const node = ReactDOM.findDOMNode(this.refs.table);
  node.style.marginTop = `-${height}`;
}

但是,在 ssr 上,组件渲染时永远不会调用 componentDidMount。所以我把这些代码放在componentWillMount中,并更新源代码如下

document.addEventListener("DOMContentLoaded", function(event) {
  const node = document.getElementById('table');
  node.style.marginTop = `-${height}`;
});

然后它还有其他问题。

document is not defined on server 

我知道原因,这是因为代码是在节点环境中运行的。没有像浏览器环境那样的文档种类。我能想到的一种方法是将代码放在renderPage 函数中,该函数用于将 React 组件呈现为服务器端Server Rendering上的 html 字符串。但是如果将事件处理程序放在顶级上下文中,它将污染其他呈现的页面。

router.get('*', ctx => {
  match({ routes: routes, location: ctx.url }, (err, redirect, props) => {
    if (err) {
      ctx.throw(err.message, 500);
    } else if (redirect) {
      ctx.redirect(redirect.pathname + redirect.search)
    } else if (props) {
      const appHtml = renderToString(<RouterContext {...props}/>);
      ctx.body = renderPage(appHtml);
    } else {
      ctx.throw(404, 'not fount');
    }
  })
})
function renderPage(appHtml) {
  return `
    <!doctype html public="storage">
    <html>
    <meta charset=utf-8/>
    <title>My First React Router App</title>
    <div id=app>${appHtml}</div>
    <script type='text/javascript'>
      document.addEventListener("DOMContentLoaded", function(event) {
        const node = document.getElementById('table');
        node.style.marginTop = `-${height}`;
      });
    </script>
  `
}

我还找到了其他解决方案。用于在全局范围内绑定事件的 React 组件。. 我不认为它是最好的解决方案。

所以我想问有没有更好的方法来操作通常放在componentDidMountcomponentDidUpdate中的 DOM 节点,如客户端渲染。

4

1 回答 1

0

像你这样操作 DOM 节点是没有用的。React 接管你的 DOM 的控制权,下次你重新渲染你的应用程序后,你设置的边距将被 React 覆盖。

我建议您使用内联样式来操作您想要处理的任何样式。

render() {
  const divStyle={'marginTop': '100px'}

  return <div style={divStyle}></div>
}

还让渲染功能处理 UI 的东西。

是否有任何理由需要在 React 生命周期中重置 marginTop 而不是直接在渲染函数中?

于 2017-10-08T06:54:15.250 回答