我熟悉用AngularJS开发客户端应用程序,但现在我想开始使用ReactJS.
我还关注ReactNative,我认为它将彻底改变移动应用程序.
React应用程序的思维方式和 struct 与Angular应用程序有何不同?最大的区别是什么?
我熟悉用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).通过将行为和标记放在一起,您可以获得很多好处:
事实证明,这是一个文本墙,所以请让我知道,如果有什么我应该澄清或扩大.