前提
前端从原生javaSCript到JQuery,再到 vue,react, Angular , 时代在前进 ,前端也一直在进步, 笔者认为 “框架” 是为业务而服务的,它是基于现有的开发,寻找其中的不足和优化 ,配合大量的业务模式而诞生出来的一种产物。
只要时代在进步, 业务在不断的发展, 框架也必然跟着进行优化重构,框架服务于现有业务,那么理解它的设计思想,提炼出适用的业务范围,学习解决不同业务的方法,才是我们学习的方向。
来源
React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护。于是痛定思痛,他们决定抛开很多所谓的“最佳实践”,重新思考前端界面的构建方式,于是就有了React。
设计思想
1.编写可预测,符合习惯的代码
所谓可预测(predictable),即容易理解的代码。
React最大的价值究竟是什么?
- 高性能虚拟DOM
- 服务器端Render
- 封装过的事件机制
- 完善的错误提示信息
尽管每一点都足以重要。但React最有价值的是声明式的,直观的编程方式。
软件工程向来不提倡用高深莫测的技巧去编程,相反,如何写出可理解可维护的代码才是质量和效率的关键。试想:
- 一个月之后你回头看你写的代码,是否一眼就明白某个变量,某个if判断的含义
- 一个新加入的同事想去增加一个小小的新功能或是修复某个Bug,他是否对自己的代码有足够的信心不引入任何副作用?
- 随着功能的增加,代码很容易变得越来越复杂,这些问题也将越来越严重,最终导致一份难以维护的代码。
而React号称,新同事甚至在加入的第一天就能开始开发新功能。
2.使用JSX直观的定义用户界面
首先我们针对todoList功能看两种类型的代码:
//Angular
<ul class="unstyled">
<li ng-repeat="todo in todoList.todos">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
复制代码
尽管我们很容易看懂这一小段模板的含义,但你却无法开始写这样的代码,因为你需要学习这一整套语法。
比如说:
- 你得知道有ng-repeat这样的标记的准确含义
- 其中的”todo in todoList.todos”看上去是repeat语法的一部分,或许还有其它语法存在
- 可以看到有{{todo.text}}这样的数据绑定,那么如果要对这段文本格式化(加一个formatter)该怎么做
- ng-model背后又需要什么样的数据结构?
那我们来看看React使用JSX是怎么实现的:
//React
render: function () {
var lis = this.todoList.todos.map(function (todo) {
return (
<li>
<input type="checkbox" checked={todo.done}>
<span className="done-{todo.done}">{todo.text}</span>
</li>);
});
return (
<ul class="unstyled">
{lis}
</ul>
);
}
复制代码
可以看到,JSX中除了另类的HTML标记之外,并没有引入其它任何新的概念(事实上HTML标记也可以完全用JavaScript去写)。
Angular中的repeat在这里被一个简单的数组方法map所替代。
在这里你可以利用熟悉的JavaScript语法去定义界面。
在你的思维过程中其实已经不需要存在模板的概念,需要考虑的仅仅是如何用代码构建整个界面。这种自然而直观的方式直接降低了React的学习门槛并且让代码更容易理解。
3.简化的组件模型:所谓组件,其实就是状态机器
组件并不是一个新的概念,它意味着某个独立功能或界面的封装,达到复用、或是业务逻辑分离的目的。
而React却这样理解界面组件:
所谓组件,就是状态机器
React将用户界面看做简单的状态机器。
当组件处于某个状态时,那么就输出这个状态对应的界面。通过这种方式,就很容易去保证界面的一致性。
在React中,你简单的去更新某个组件的状态,然后输出基于新状态的整个界面。
React负责以最高效的方式去比较两个界面并更新DOM树。
复制代码
理解:
例如,某个组件有只读和编辑两个状态。
一般的思路可能是提供beginEditing()和endEditing()这样的方法来实现切换。
而在React中,需要做的是setState({editing: true/false})。在组件的输出逻辑中负责正确展现当前状态。
这种方式,你不需要考虑beginEditing和endEditing中应该怎样更新UI,而只需要考虑在某个状态下,UI是怎样的。显然后者更加自然和直观。
组件是React中构建用户界面的基本单位。它们和外界的交互除了状态(state)之外,还有就是属性(props)。
事实上,**状态**更多的是一个组件内部去自己维护
而**属性**则由外部在初始化这个组件时传递进来(一般是组件需要管理的数据)。
React认为属性应该是只读的,一旦赋值过去后就不应该变化。
复制代码
4.每一次界面变化都是整体刷新
数据模型驱动UI界面的两层编程模型
概念角度看上去是直观的,而在实际开发中却困难重重。一个数据模型的变化可能导致分散在界面多个角落的UI同时发生变化。界面越复杂,这种数据和界面的一致性越难维护。
开发者为了维护这种依赖更新,有时不得不触发大范围的界面刷新,而其中很多并不真的需要。React的初衷之一就是,既然整体刷新一定能解决层叠更新的问题,那我们为什么不索性就每次都这么做呢?让框架自身去解决哪些局部UI需要更新的问题。这听上去非常有挑战,但React却做到了,实现途径就是通过虚拟DOM(Virtual DOM)。
总结感想
当我学习这一篇文章进而精简的时候,我发现大部分都在怼Vue,哈哈。
JSX 和 Vue 的模板 渲染方式
组件思想
通信思想
渲染思想粗看倒是差不多,以后根据源码在品味一番
个人感觉,三大框架发布前,国内的前端,很多都不是cs专业出身,更偏重UI,美工方向的,对于数据结构基础方面可能比较薄弱。
但不管怎么说三大框架都是解决了dom性能和操作问题,模板和复用问题。
React 和Vue在我看来其实没有什么优劣之分,Vue的开发我觉得更偏向与老前端的设计思维,比较容易接受,好上手。
而React可能更多从后端工程师的思维来进行框架的设计。
以后对于中小型项目,我可能会偏向与Vue开发。
对于大型项目,从软件过程方面,我觉得React会比Vue更加合适,同时对于开发者面向对象,数据结构的要求也会更高,基于逻辑构建页面。