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

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

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

推荐答案

Directives

如果你熟悉Angular,那么思考React如何工作的方法就是想象只使用Angular指令.React没有任何控制器、服务、工厂或依赖注入的概念.If只关注组件(Angular 方面的指令).

这也是Angular以Angular 2开头的方式.Angular 2引入了一个称为组件的概念,并删除了指令、控制器和服务/工厂的概念.Angular 2仍然使用DI,但您没有将类绑定到Angular世界(在Angular 1中就是这样).

Scopes

因此Angular使用作用域进行数据绑定,任何绑定到作用域(或父作用域)的模板都可以从该作用域读取和打印数据,甚至可以修改该作用域.React中没有作用域的概念,主要是因为React不像Angular那样进行脏判断,还因为React使用常规Javascript作用域来确定视图可用的变量/对象.稍后再谈.

Templating

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

在JSX中,可以将元素的属性值设置为字符串(如<div className="myClass">)或Javascript表达式(如<div className={myClassVariable}>,其中myClassVariable是常规Javascript变量).JSX中{}之间的任何内容都只是简单的旧Javascript.你可以传递一个对象、一个函数、一个字符串等等.当你试图在JSX中使用一个未定义的变量时,你的linter可以帮助你,这是你的linter在Angular 模板中使用属性时无法做到的.

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

Data binding/mutation/state

Angular使用作用域定义应用程序状态.该范围可以从视图、控制器或指令中进行变异.作用域相互继承,因此如果您可以访问某个作用域,还可以修改父作用域.这是大型Angular 应用程序难以管理的原因之一,因为应用程序的状态可以在很多地方更改.而观察那些引发其他变化的变化会让人更难理解.

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

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

但是传递给函数的参数永远不应该在接收它们的函数中更改.他们可以创建一个局部变量,并将其值赋给参数值,然后更改该局部变量.但它永远不应该直接改变论点.

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

React知道组件的状态和props 何时更改,因为要更改组件的状态时必须显式调用setState.它知道什么时候props 会发生变化,因为当父组件渲染时,您会将props 传递给组件.

状态更改后,React将重新渲染组件(及其所有子组件).请注意,它只会将它们重新渲染为组件的虚拟表示形式.然后,它会对自上次渲染以来发生的更改进行区分,并且只有实际的更改应用于DOM.这基本上就是React的秘密酱汁.编程模型是在每次发生事情时重新渲染所有内容,但只做所需的最小工作量.

Where are my controllers!?

就像我说的,React没有任何控制器的概念,它只关注组件.也就是说,在使用React时,您仍然经常使用控制器/视图分离.您有处理数据获取和状态管理的组件(有时称为视图控制器),但很少进行渲染.相反,您有一个单独的组件,它对数据获取知之甚少,对渲染知之甚少.因此视图控制器组件知道如何获取数据,然后将数据传递给知道如何渲染数据的组件.一个简单的例子如下:

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不会强迫你这样做.

Data binding

Angular使用数据绑定使视图与视图模型保持同步.React根本不使用数据绑定.可以说Angular监视视图模型的更改并相应地更新DOM,而React监视从组件返回的JSX的更改,并相应地更新DOM.

Separation of concerns

很多人对React持怀疑态度,因为他们觉得React不能很好地分离关注点.而JSX往往是这场争论的目标.他们觉得在Javascript中添加标记是对视图和行为的混合担忧.如果你习惯使用Angular,你可能不同意在标记中描述行为是个坏主意(因为你也使用Angular).一个经常被吹捧的反驳是React"分离关注点,而不是技术",因为视图(标记)和它的行为不是分离的关注点,而是传统上分离的技术(HTML和Javascript).通过将行为和标记放在一起,您可以获得很多好处:

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

事实证明,这是一个文本墙,所以请让我知道,如果有什么我应该澄清或扩大.

React-native相关问答推荐

添加REACT-Native-SVG时出现错误-失败:构建失败并出现异常

如何在底部标签导航中添加顶部标签

axios 在react native 中给出 [AxiosError: Network Error]

找不到变量:firebase/react native(expo)上的 IDBIndex

如何在 React / React Native 中使用 Emscripten 编译的 JavaScript

No component found for view with name "ARTShape"

@react-navigation/stack 与 @react-navigation/native-stack 有什么区别?

如何在react native应用程序名称中添加空格?

React-Native: measure测量一个视图

react-native android应用程序中的underlineColorAndroid is not a valid style property错误

ScrollView visible Scroll Bar

React Native + Jest EMFILE:too many open files error

react-native async 函数返回 promise 但不返回我的 json 数据?

如何在 React 中使用带有钩子的生命周期方法?

检测是否通过推送通知打开了 React Native iOS 应用

如何更改键盘上的 return按钮?

如何在 React Native 的 MapView 中设置标记

如何在 React Native 中禁用图像淡入效果?

Super expression must either be null or a function, not undefined

如何升级 react-native gradle 版本