首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从jQuery转到React.js?

如何从jQuery转到React.js?
EN

Stack Overflow用户
提问于 2014-05-11 04:08:15
回答 1查看 47.5K关注 0票数 73

我已经读了几天关于React的文章。我可以理解我正在看的大部分内容,但我对自己的写作能力并不是完全有信心。我一直在开发一个小的web应用程序,它通过jQuery和互相添加元素来生成所有的html。我想尝试用React重新构建它,因为我相信它会更快。这个JSFiddle是我正在做的这类事情的一个小例子。你会怎么用React来写呢?

JS:

代码语言:javascript
复制
function remove() {
    this.remove();
}

function timed_append_new_element() {
    setTimeout(function () {
        var added_content = $("<span />", {
            class: "added_content",
            text: "Click to close",
            click: remove
        });
        container.append(added_content);
    }, 3000);
}

function append_new_element() {
    var added_content = $("<span />", {
        class: "timed_added_content",
        text: "Click to close",
        click: remove
    });
    container.append(added_content);
}


var container = $("<div />", {
    class: "container"
});
var header = $("<span />", {
    class: "header",
    text: "jQuery to React.js Header"
});
var add_button = $("<button />", {
    class: "add_button",
    text: "Add Element",
    click: append_new_element
});
var timed_add_button = $("<button />", {
    class: "add_button",
    text: "Add Element in 3 seconds",
    click: timed_append_new_element
});
container.append(header);
container.append(add_button);
container.append(timed_add_button);
$("body").append(container);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-11 23:27:51

有几个基本原则需要记住,它们可以帮助你构建一个好的React应用程序:

您的UI应该是data的一个函数

在许多"jQuery汤“风格的应用程序中,应用程序的业务逻辑、应用程序的数据和UI交互代码都混合在一起。这使得这类应用程序很难调试,尤其是难以扩展。与许多现代客户端应用程序框架一样,React强调UI只是数据的一种表示形式。如果您希望更改UI,则应该更改一段数据,并允许框架使用任何绑定系统来为您更新UI。

在React中,每个组件(理想情况下)都是两段数据的函数-传递给组件实例的属性和组件内部管理的状态。给定相同的属性(或"props")和状态,组件应该以相同的方式呈现。

这可能是一个抽象的想法,没有具体的例子,所以在我们继续下一步的时候请记住这一点。

请勿接触DOM

与其他数据绑定框架相比,在React中,如果可能的话,您应该尽量不直接操作DOM。React的许多性能和复杂性特征之所以成为可能,是因为React在内部使用了一个带有差分算法的虚拟DOM来操作真实的DOM。每当您构建一个组件并执行自己的DOM操作时,您都应该问问自己,是否可以使用React的虚拟DOM特性更地道地构建相同的特性。

当然,有时您需要访问DOM,或者您可能希望合并一些jQuery插件而不在React中重新构建它。在这种情况下,React为您提供了良好的component lifecycle hooks,您可以使用它来确保React的性能不会受到太大影响(或者,在某些情况下,为了防止组件完全崩溃)。

不操纵DOM与上面的"UI作为数据的函数“密切相关。

颠倒数据流

在大型React应用程序中,可能很难跟踪哪个子组件正在管理某个应用程序数据。出于这个原因,React团队建议将数据操作逻辑放在一个中心位置。要做到这一点,最直接的方法是将回调传递给子组件;Facebook还开发了一个名为Flux的体系结构,该体系结构具有its own website

创建可组合组件

很多时候,编写一个管理多个状态或多个UI逻辑的大型组件是很有诱惑力的。在可能的情况下(并且在合理的范围内),您应该考虑将较大的组件拆分成对单个数据或UI逻辑进行操作的较小组件。这使得扩展和移动应用程序的各个部分变得更加容易。

注意可变数据

由于组件状态只能通过从组件内部调用this.setState来更新,因此提防可变数据是很有帮助的。当有多个功能(或组件!)时更是如此可能会在同一时间内更新可变对象;React可能会尝试批量处理状态更改,而您可能会丢失更新!正如Eliseu Monar的评论中所提到的,在对可变对象进行变异之前,请考虑克隆它们。React有immutability helpers可以提供帮助。

另一种选择是完全放弃直接保持可变数据结构的状态;上面提到的Flux模式是对这种想法的一种有趣的采用。

React网站上有一篇很棒的文章,名为Thinking in React,它介绍了如何将一个想法或模型转化为React应用程序,我强烈建议您阅读这篇文章。作为一个具体的例子,让我们看一下您提供的代码。实际上,您只需要管理一段数据:存在于container元素中的内容列表。对UI的所有更改都可以通过对该数据的添加、删除和更改来表示。

通过应用上面的原则,您的最终应用程序可能如下所示:

代码语言:javascript
复制
/** @jsx React.DOM */

var Application = React.createClass({
  getInitialState: function() {
    return {
      content: []
    };
  },

  render: function() {
    return (
      <div className="container">
        <span className="header">jQuery to React.js Header</span>
        <button className="add_button"
                onClick={this.addContent}>Add Element</button>
        <button className="add_button"
                onClick={this.timedAddContent}>Add Element in 3 Seconds</button>
        {this.state.content.map(function(content) {
          return <ContentItem content={content} removeItem={this.removeItem} />;
        }.bind(this))}
      </div>
    );
  },

  addContent: function() {
    var newItem = {className: "added_content", text: "Click to close"},
        content = this.state.content,
        newContent = React.addons.update(content, {$push: [newItem]});
    this.setState({content: newContent});
  },

  timedAddContent: function() {
    setTimeout(function() {
      var newItem = {className: "timed_added_content", text: "Click to close"},
          content = this.state.content,
          newContent = React.addons.update(content, {$push: [newItem]});
      this.setState({content: newContent});
    }.bind(this), 3000);
  },

  removeItem: function(item) {
    var content = this.state.content,
        index = content.indexOf(item);
    if (index > -1) {
      var newContent = React.addons.update(content, {$splice: [[index, 1]]});
      this.setState({content: newContent});
    }
  }
});

var ContentItem = React.createClass({
  propTypes: {
    content: React.PropTypes.object.isRequired,
    removeItem: React.PropTypes.func.isRequired
  },

  render: function() {
    return <span className={this.props.content.className}
                 onClick={this.onRemove}>{this.props.content.text}</span>;
  },

  onRemove: function() {
    this.props.removeItem(this.props.content);
  }
});

React.renderComponent(<Application />, document.body);

您可以在this JSFiddle中查看实际运行的代码:http://jsfiddle.net/BinaryMuse/D59yP/

该应用程序由两个组件组成:一个名为Application的顶级组件(在其状态下)管理一个名为content的数组,以及一个名为ContentItem的组件,它表示该数组中单个项的UI和行为。Applicationrender方法为内容数组中的每一项返回一个ContentItem元素。

需要注意的是,管理content数组中的值的所有逻辑都是在Application组件中处理的;ContentItem组件被传递了一个对ApplicationremoveItem方法的引用,当单击该方法时,ContentItem将委托该方法。这将所有用于操作状态的逻辑都保留在顶级组件中。

票数 173
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23585765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档