【问题标题】:How do I keep document.title updated in React app?如何在 React 应用程序中保持 document.title 的更新?
【发布时间】:2014-12-03 16:34:10
【问题描述】:

由于 React 没有任何内置方法来管理 document.title,我曾经将它设置在我的路由处理程序的 componentDidMount 中。

但是现在我需要根据异步获取的state 修改标题。我开始在 componentDidUpdate 中添加分配,但时不时我忘记将 document.title 分配到某些页面中,并且之前的标题一直存在,直到我终于注意到它。

理想情况下,我想要一种以声明方式表达document.title 的方式,而无需分配它。考虑到我希望能够在多个嵌套级别指定文档标题,某种“假”组件可能最方便:

  • 在顶层(默认标题);
  • 在页面级别(对于某些页面,但不是全部);
  • 有时,在内部组件级别(例如,用户在字段中输入内容)。

附加要求:

  • 子项中指定的标题应覆盖父项指定的标题;
  • 可靠(保证在更改路线时进行清理);
  • 不应发出任何 DOM(即,没有 hack 组件返回 <noscript>);
  • 我正在使用 react-router,但如果此组件也可以与其他路由器一起使用会更好。

有什么我可以用的吗?

【问题讨论】:

  • 在你的渲染函数中有 document.title = this.state.documentTitle 有什么问题?或者先检查更改做类似的事情。
  • @Mike:首先,您不应该在render 中这样做,它应该没有副作用。你的意思可能是componentDidUpdate。好吧,随着应用程序的增长,如果您希望它出现在某些屏幕上,那么保持document.title 的一致性变得越来越困难,但对其他屏幕使用一些默认标题。只需要一页就忘记指定标题,它会变得陈旧。

标签: javascript dom reactjs react-router


【解决方案1】:

与此同时,3 年过去了! ;-)
如果您想操作除标题之外的其他页眉(如描述、规范等),react-document-meta NPM 依赖可能是一个不错的选择。

【讨论】:

    【解决方案2】:
    class Layout extends React.Component {
      constructor(props){
        super(props);
        document.title = this.props.title;
      }
      render(){
        return(
          <div>
          </div>
        );
      }
    }
    

    然后&lt;Layout title="My Title"/&gt; 就这么简单!

    【讨论】:

      【解决方案3】:

      看看 NFL 的react-helmet

      【讨论】:

      • react-helmet 太棒了!
      【解决方案4】:

      试试react-frozenhead,它实际上比 react-document-title 更复杂 - 它允许我们更改标题、描述和部分中的任何其他内容。

      【讨论】:

        【解决方案5】:

        我为此写了react-document-title

        它提供了一种在单页应用程序中指定document.title 的声明方式。
        如果您想在将组件渲染为字符串后在服务器上获取标题,请调用DocumentTitle.rewind()

        特点

        • 不发出 DOM,甚至不发出 &lt;noscript&gt;
        • 与普通的 React 组件一样,可以使用其父级的 propsstate
        • 可以在整个应用程序的许多地方定义;
        • 支持任意级别的嵌套,因此您可以定义应用范围和页面特定的标题;
        • 适用于客户端和服务器。

        示例

        假设你使用类似react-router:

        var App = React.createClass({
          render: function () {
            // Use "My Web App" if no child overrides this
            return (
              <DocumentTitle title='My Web App'>
                <this.props.activeRouteHandler />
              </DocumentTitle>
            );
          }
        });
        
        var HomePage = React.createClass({
          render: function () {
            // Use "Home" while this component is mounted
            return (
              <DocumentTitle title='Home'>
                <h1>Home, sweet home.</h1>
              </DocumentTitle>
            );
          }
        });
        
        var NewArticlePage = React.createClass({
          mixins: [LinkStateMixin],
        
          render: function () {
            // Update using value from state while this component is mounted
            return (
              <DocumentTitle title={this.state.title || 'Untitled'}>
                <div>
                  <h1>New Article</h1>
                  <input valueLink={this.linkState('title')} />
                </div>
              </DocumentTitle>
            );
          }
        });
        

        来源

        我会跟踪已挂载的实例,并且仅在更新、挂载或卸载时使用分配给已挂载实例堆栈顶部 DocumentTitletitle。在服务器上,componentWillMount 会触发,但我们不会得到didMountwillUnmount,因此我们引入了DocumentTitle.rewind(),它返回一个字符串并销毁状态以准备下一个请求。

        var DocumentTitle = React.createClass({
          propTypes: {
            title: PropTypes.string
          },
        
          statics: {
            mountedInstances: [],
        
            rewind: function () {
              var activeInstance = DocumentTitle.getActiveInstance();
              DocumentTitle.mountedInstances.splice(0);
        
              if (activeInstance) {
                return activeInstance.props.title;
              }
            },
        
            getActiveInstance: function () {
              var length = DocumentTitle.mountedInstances.length;
              if (length > 0) {
                return DocumentTitle.mountedInstances[length - 1];
              }
            },
        
            updateDocumentTitle: function () {
              if (typeof document === 'undefined') {
                return;
              }
        
              var activeInstance = DocumentTitle.getActiveInstance();
              if (activeInstance) {
                document.title = activeInstance.props.title;
              }
            }
          },
        
          getDefaultProps: function () {
            return {
              title: ''
            };
          },
        
          isActive: function () {
            return this === DocumentTitle.getActiveInstance();
          },
        
          componentWillMount: function () {
            DocumentTitle.mountedInstances.push(this);
            DocumentTitle.updateDocumentTitle();
          },
        
          componentDidUpdate: function (prevProps) {
            if (this.isActive() && prevProps.title !== this.props.title) {
              DocumentTitle.updateDocumentTitle();
            }
          },
        
          componentWillUnmount: function () {
            var index = DocumentTitle.mountedInstances.indexOf(this);
            DocumentTitle.mountedInstances.splice(index, 1);
            DocumentTitle.updateDocumentTitle();
          },
        
          render: function () {
            if (this.props.children) {
              return Children.only(this.props.children);
            } else {
              return null;
            }
          }
        });
        
        module.exports = DocumentTitle;
        

        【讨论】:

        • 亲爱的投票者,您能否提出解决此问题的其他解决方案?
        • 这个 npm 包仍然可以用来设置文档标题吗?我正在使用 React 15.1.0。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-01
        相关资源
        最近更新 更多