【问题标题】:ReactJS component rendering and how to append elements to the div the component is mounted onReactJS 组件渲染以及如何将元素附加到组件所安装的 div
【发布时间】:2015-09-07 12:01:33
【问题描述】:

我有这个用例,页面上有一个“加载更多”按钮,用于从 API 端点获取更多项目,因此我希望这些项目在到达时附加到 DOM。问题是 Web 服务器提供的 HTML 页面在相同的 item-list div 容器中附带了一些额外的列表项(如下所示),我在页面加载时使用空数据/道具安装了我的 React 组件。

<div class="item-list">
  <div class="item-list__child-item"></div>
  <div class="item-list__child-item"></div>
  ...
  <div class="item-list__child-item"></div>
</div>

我的假设是,如果我以 ReactJS 方式处理此问题,一旦我从服务器 (REST) 获取更多项目并将这些项目附加到“itemList”状态数组,react 将以某种方式替换所有保存安装组件的“项目列表”div。

我认为一种快速的解决方法是可行的,它不依赖于同构的东西并在服务器上预渲染反应组件,是创建一个单独的同级 div 具有相同的 div 类名称'item -list' 并添加一个 id 属性来挂载组件,因此生成的 HTML 如下所示:

<div class="item-list">
  <div class="item-list__child-item"></div>
  <div class="item-list__child-item"></div>
  ...
  <div class="item-list__child-item"></div>
</div>

<div class="item-list" id="react-component-name"></div>

也许有一种更简洁的方法可以做到这一点,而无需涉及同构的东西,或者我不了解 React 的概念及其工作原理。无论如何,您将不胜感激您对此的任何指示。

【问题讨论】:

  • 您可以尝试危险地SetInnerHTML 将原始html 设置为.item-list
  • 试试这个演示 jsfiddle.net/x4jjry04

标签: reactjs


【解决方案1】:

好的,您的问题并不清楚,但是由 HTML 中生成的内容表示的数据将与您的数据完全不同将通过 AJAX 获取。

有一个简单的解决方案。与其创建一个与原始 DOM 布局相邻的全新 DOM 元素,不如获取已经存在的数据,将其存储到数组中,然后将通过 AJAX 获取的新数据附加到该数组中大批。这样,您将获得 React 的 DOM diffing 的好处。为什么有用?也许您想让用户对数据进行排序,或者直接与数据交互,同时它仍将完全控制父 React 组件。

无论如何,看看这个小提琴:https://jsfiddle.net/x4jjry04/3/。它基于 Paul Booblic 的小提琴。

var Page = React.createClass({ 
  getDefaultProps: function () {
    return {
      items: []
    }
  },
  getInitialState : function(){
    return{
      items : this.props.items
    }
  },
  componentDidMount: function () {
    // Mimics an AJAX call, but replace this with an actial AJAX call.
    setTimeout(function () {
      var dataFromAjax = ['one', 'two', 'three'];
      this.setState({
        items: this.state.items.concat(dataFromAjax)
      });
    }.bind(this));
  },
  addClick : function(){
    this.state.items.push("more");
    this.forceUpdate();
  },
  render : function(){
    return <div>{this.state.items.map(function(item){return <div className="bla-bla-class">{item}</div>})}<br/><div onClick={this.addClick}>ADD</div></div>;
  }
});

var elements = document.querySelectorAll('.item-list__child-item');

var initialvalues = Array.prototype.slice
  .call(elements)
  .map(function (div) {
    return div.innerHTML;
  });

React.render(<Page items={initialvalues} />, document.body);

【讨论】:

  • 出色的解决方法,非常感谢!我刚刚提出的一个建议是在 HTML 源代码上打印一个
  • “我刚刚提出的一个建议是在 HTML 源代码上打印一个
【解决方案2】:

查看这个简单的小提琴演示:

https://jsfiddle.net/x4jjry04

var Page = React.createClass({ 
   getInitialState : function(){
   return{
    items : ["one","two","three"]
   }
  },
  addClick : function(){
   this.state.items.push("more");
   this.forceUpdate();

  },
  render : function(){
   return <div>{this.state.items.map(function(item){return <div className="bla-bla-class">{item}</div>})}<br/><div onClick={this.addClick}>ADD</div></div>;
  }
 });

React.render(<Page />, document.body);

【讨论】:

  • 感谢小提琴演示,这几乎就是我想要做的!问题是安装react组件的div已经有一些页面加载时加载的HTML内容,渲染时不会react替换内容吗?
  • 不,react rerender only changed elements
  • 您希望在 div 中存储什么样的内容?您可以在 render 中生成它或保留静态 div 并在 div id="appended" jsfiddle.net/yho4rL0p 中附加动态 div
  • 是的,这就是我在问题中提出的建议,但不确定是否可行。我接受了 Salehen 的建议,因为他在回答中陈述的原因正是我所追求的。喜欢玩你的小提琴来了解更多关于渲染是如何工作的。谢谢!
【解决方案3】:

我假设您正在使用 react 服务器端来呈现列表?

在页面加载时,您从服务器获取原始列表并让组件“重新渲染”元素。 re-render 是用引号引起来的,因为除非列表发生变化,否则 React 不会真正更新列表。现在您已经设置了一个按预期工作的组件,您可以根据需要向列表中添加元素。

同构/通用 React 的一般理念是,您将您的应用程序视为普通的单页应用程序,并让 React 处理脏检查的魔力。

这也意味着您可以在服务器上渲染时使用相同的组件,因为您的组件不包含任何客户端特定的代码。

【讨论】:

  • 实际上没有服务器端的react渲染,它只是一个html文件,但初始项目已经包含在要安装react组件的DIV中。出于 SEO 的目的,我需要在 HTML 中嵌入该初始列表。对不起,如果我没有说清楚。
猜你喜欢
  • 2023-01-16
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
  • 2017-07-10
  • 2019-10-14
  • 2018-07-20
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多