如果我有 AngularJS 背景,“在 ReactJS 中思考”?

“Thinking in ReactJS" if I have a AngularJS background?

我熟悉使用 AngularJS 开发客户端应用程序,但现在我想开始使用 ReactJS。

我也关注 ReactNative,我认为它将彻底改变移动应用程序。

React应用程序的思维方式和结构与Angular有何不同?最大的区别是什么?

ReactJS 就是 (reusable) components, which imo can best be compared to Angular's directives

所以我想说,想象一下在 AngularJS 中创建一个只有指令的应用程序:)

几周前我开始使用 ReactJS 进行开发,起初它很奇怪(在你的 JS 中编写模板代码,wtf?),但现在我已经习惯了。我最近也开始玩 React-Native,它很棒!

我现在可以在这里列出 Angular 和 React 之间的很多区别,但是其他人已经写了一些不错的文章,所以我建议您阅读这些文章以获得更清晰的想法。

然后还有awesome-react,react 库、资源、教程、文章的汇编(随便你说,它就在那里)

关于您的问题,这部分可能是您最感兴趣的部分:

More articles on the approach of ReactJS and comparisons with other frameworks

指令

如果您熟悉 Angular,那么思考 React 工作原理的方法就是想象仅使用指令来使用 Angular。 React 没有任何控制器、服务、工厂或依赖注入的概念。如果仅关注组件(Angular 术语中的指令)。

这也是 Angular 以 Angular 2 为首的方式。 Angular 2 引入了一个称为组件的概念,并删除了指令、控制器和 services/factories. Angular 2 仍然使用 DI,但你没有将你的 类 绑定到 Angular 世界(你在 Angular 1 中这样做)。

作用域

因此 Angular 使用范围进行数据绑定,绑定到范围(或父范围)的任何模板都可以从该范围读取和打印数据,甚至可以修改该范围。 React 中没有作用域的概念,主要是因为 React 不像 Angular 那样进行脏检查,还因为 React 使用常规的 Javascript 作用域来确定哪些 variables/objects 可用于看法。稍后会详细介绍。

模板化

这是一个重要的区别。在 Angular 中,您可以在不同的文件中或作为 Javascript 字符串定义模板。在 React 中,您在 Javascript 或 JSX 中定义视图。 JSX 是对 Javascript 的类似 XML/HTML 的语言扩展,它允许您描述 HTML(或本机视图,如 React Native)。

在 JSX 中,您可以将元素的 属性 值设置为 <div className="myClass"> 之类的字符串或使用 Javascript 表达式,如下所示: <div className={myClassVariable}> where myClassVariable 是一个常规的 Javascript 变量。 JSX 中 {} 之间的任何东西都只是普通的旧 Javascript。您可以传递一个对象、一个函数、一个字符串等。当您尝试在 JSX 中使用未定义的变量时,您的 linter 可以帮助您,这是您在 Angular 中使用属性时 linter 无法做到的事情模板。

通过在 JSX 而不是 HTML 字符串中定义视图,您可以随意使用 Javascript 的全部功能。您不需要 Angular 范围之类的东西,因为您已经有一个 Javascript 范围,它决定了您可以在视图中使用什么。这就是擅长 Angular 只会让你擅长 Angular,而擅长 React 也会让你成为更好的 Javascript 程序员。

数据binding/mutation/state

Angular 使用范围来定义应用程序状态。该范围可以从视图、控制器或指令中改变。作用域相互继承,因此如果您可以访问一个作用域,您还可以修改父作用域。这是大型 Angular 应用程序往往难以管理的原因之一,因为可以从很多地方更改应用程序的状态。观察那些触发其他变化的变化使它更难掌握。

React 使用两个概念,称为 props 和 state。将它们想象成常规的 Javascript 函数。 State 是函数中定义的变量,props 是传递给函数的参数。

函数中定义的变量可以在该函数中更改,并且可以作为参数传递给其他函数。

但是传递给函数的参数永远不应在接收它们的函数中更改。他们可以创建一个局部变量并将其值分配给参数值并更改该局部变量。但它不应该直接改变参数。

所以 props 是从父组件传递给组件的值。接收 props 的组件不拥有它们,也不知道它们来自哪里,就像函数的参数一样。另一方面,状态由组件拥有,组件可以像局部变量一样以任何方式更改它。

React 知道组件的状态和 props 何时更改,因为当您想要更改组件的状态时必须显式调用 setState。它知道 props 何时更改,因为您在父组件呈现时将 props 传递给组件。

当状态改变时,React 重新渲染组件(及其所有子组件)。请注意,它只会将它们重新呈现为组件的虚拟表示。然后它对自上次渲染以来发生的变化进行比较,只有实际的变化才会应用到 DOM。这本质上是 React 的秘密武器。编程模型是在每次发生事情时重新渲染所有内容,但只做所需的最少工作量。

我的控制器呢!?

正如我所说,React 没有任何控制器的概念,它只关注组件。也就是说,当你使用 React 时,你仍然经常使用 controller/view 分隔。您拥有处理数据获取和状态管理但很少进行渲染的组件(有时称为视图控制器)。相反,您有一个单独的组件,它对数据获取知之甚少,而对渲染知之甚少。所以视图控制器组件知道如何获取数据,然后它将数据传递给知道如何呈现它的组件。一个简单的例子是这样的:

var TodoItemsComponent = React.createClass({
  getInitialState: function () {
    return {
      todoItems: null
    }
  },
  componentDidMount: function () {
    var self = this;
    TodoStore.getAll().then(function (todoItems) {
      self.setState({todoItems: todoItems});
    });

    TodoStore.onChange(function (todoItems) {
      self.setState({todoItems: todoItems});
    });
  },
  render: function () {
    if (this.state.todoItems) {
      return <TodoListComponent todoItems={this.state.todoItems} />;
    } else {
      return <Spinner />;
    }
  }
});

var TodoListComponent = React.createClass({
  render: function () {
    return (
      <ul>
        {this.props.todoItems.map(function (todo) {
          return <li>{todo.text}</li>;
        })}
      </ul>
    );
  }
});

在此示例中,有两个组件。一种只关心数据获取,一种只关心渲染。它们都是 React 组件,但它们的职责截然不同。这是控制器和指令在 Angular 中的分离,但 React 不会强迫您这样做。

数据绑定

Angular 使用数据绑定使视图与视图模型保持同步。 React 根本不使用数据绑定。您可以说 Angular 监视视图模型的更改并相应地更新 DOM,而 React 监视您 return 来自组件的 JSX 更改,并更新 DOM因此。

关注点分离

很多人对 React 持怀疑态度,因为他们认为 React 没有很好地分离关注点。而 JSX 通常是该争论的目标。他们觉得在您的 Javascript 中添加标记会混淆对视图和行为的担忧。如果您习惯于 Angular,您可能不同意在标记中描述行为是个坏主意(因为您也在 Angular 中这样做)。一个经常被吹捧的反驳论点是 React "separates concerns, not technologies" 因为视图(标记)和它的行为不是独立的关注点,而只是传统上独立的技术(HTML 和 Javascript)。通过共同定位行为和标记,您可以获得很多好处:

  1. 很容易看出您是否有未使用的变量或函数。使用 Angular,您必须在模板中查找表达式,并查找所有可以访问该范围的地方,以查看范围内是否有未使用的变量或函数。
  2. 一个组件被隔离到一个文件中,您不必在 Javascript 文件和模板文件之间来回切换。
  3. 更改行为通常需要更改标记,反之亦然。因此,将其保存在一个文件中可以更轻松地查看需要进行哪些更改。

原来是文字墙,所以如果有什么我应该澄清或扩展的,请告诉我。