[干货分享] 三大前端技术(React,Vue,Angular)探密

【引言】

前段时间写过一篇关于前端技术的概括性文章《前端技术的选择](http://3ms.huawei.com/km/blogs/details/7971337),本文就对于当下顶级的前端开发技术做个相对详尽的探究,目的是为了解开这些前端技术的面纱,看看各自的庐山真面目。

 

React

React(也被称为React.jsReactJS)是一个用于构建用户界面的JavaScript库。它由Facebook和一个由个人开发者和公司组成的社区来维护。

 

React可以作为开发单页或移动应用的基础。然而,React只关注向DOM渲染数据,因此创建React应用通常需要使用额外的库来进行状态管理和路由,ReduxReact Router分别是这类库的例子。

基本用法

下面是一个简单的ReactHTML中使用JSXJavaScript的例子。

 

<div id="myReactApp"></div>

 

<script type="text/babel">

  function Greeter(props) {

    return <h1>{props.greeting}</h1>;

  }

  var App = <Greeter greeting="Hello World!" />;

  ReactDOM.render(Appdocument.getElementById("myReactApp"));

</script>

 

 

Greeter函数是一个React组件,它接受一个属性问候语。变量AppGreeter组件的一个实例,其中问候语属性被设置为 "Hello World"。然后,ReactDOM.render方法将我们的Greeter组件渲染在DOM元素(id myReactApp)中。

 

web浏览器中显示时,结果将是:

 

<div id="myReactApp">

  <h1>Hello World!</h1>

</div>

 

 

显著特点

 

组件化

React代码由称为组件的实体组成。组件可以使用React DOM库渲染到DOM中的一个特定元素。当渲染一个组件时,可以传入被称为 "props "的值。

 

ReactDOM.render(<Greeter greeting="Hello World!" />, document.getElementById('myReactApp'));

 

 

React中声明组件的两种主要方式是通过功能函数组件和基于类的组件。

 

功能函数组件

 

功能组件是用一个函数声明,用来返回一些JSX

 

const Greeting = (props=> <div>Hello, {props.name}!</div>;

 

 

类组件

基于类的组件是使用ES6类来声明的。它们也被称为 "有状态 "组件,因为它们的状态可以在整个组件中保持,并且可以通过props传递给子组件。

class ParentComponent extends React.Component {

  state = { color: 'green' };

  render() {

    return (

      <ChildComponent color={this.state.color} />

    );

  }

}

 

虚拟 DOM

另一个值得注意的特点是React使用了虚拟文档对象模型,也就是虚拟DOMReact创建了一个内存中的数据结构缓存,计算得出变化差异,只渲染实际变化的子组件从而高效地更新浏览器显示的DOM

 

生命周期方法

生命周期方法是指在组件的生命周期内,允许在设定的点执行代码的hooks处理函数。

 

l  shouldComponentUpdate允许开发者在不需要渲染的情况下,通过返回false来防止不必要的重新渲染组件。

l  componentDidMount是在组件 "挂载 "后调用的(组件已经在用户界面中创建了,通常是通过将其与DOM节点关联起来)。这通常用于通过API从远程数据源触发数据加载。

l  componentWillUnmount是在组件被拆解或 "解挂 "之前立即调用的。这通常用于清除组件的资源依赖关系,这些依赖关系不会随着组件的卸载而简单地被移除(例如,移除任何与组件相关的setInterval()实例,或者因为组件的存在而在 "文档 "上设置的 "eventListener")。

l  render是最重要的生命周期方法,也是任何组件中唯一必须存在的方法。它通常在每次更新组件的状态时都会被调用。

 

JSX

JSX,即JavaScript XML,是对JavaScript语言语法的扩展。JSX在外观上类似于HTML,它提供了一种开发者熟悉的语法结构化组件渲染的方法。React组件通常是使用JSX编写的,尽管不一定非要使用JSX(组件也可以用纯JavaScript编写)。JSX类似于FacebookPHP创建的另一种名为XHP的扩展语法。

 

JSX代码的一个例子:

class App extends React.Component {

  render() {

    return (

      <div>

        <p>Header</p>

        <p>Content</p>

        <p>Footer</p>

      </div>

    );

  }

}

 

 

嵌套元素

同一层次上的多个元素需要被包裹在一个容器元素中,如上图中的<div>元素。

 

属性

JSX提供了一系列的元素属性,旨在对应HTML提供的属性。这些自定义的属性也可以传递给组件,所有的属性都会被组件作为props接收。

 

JavaScript表达式

JavaScript表达式(但不是语句)可以在JSX内部通过大括号{}使用。

<h1>{10+1}</h1>

 

上面代码的显示结果是:

<h1>11</h1>

 

条件语句

If-else语句不能在JSX中使用,但可以使用条件表达式来代替。下面的例子当i1 { i === 1 ? 'true' : 'false' } 呈现为字符串 'true'

 

class App extends React.Component {

  render() {

    const i = 1;

    return (

      <div>

        <h1>{ i === 1 ? 'true' : 'false' }</h1>

      </div>

    );

  }

}

 

结果会是:

<div>

  <h1>true</h1>

</div>

 

函数和JSX可以用于条件表达式中:

class App extends React.Component {

  render() {

    const sections = [123];

    return (

      <div>

        {sections.length > 0 && sections.map(n => (

            /* 'key'必须唯一 */

            <div key={"section-" + n}>Section {n}</div>

        ))}

      </div>

    );

  }

}

 

结果会是:

 

 

<div>

  <div>Section 1</div>

  <div>Section 2</div>

  <div>Section 3</div>

</div>

 

JSX编写的代码需要被Babel等工具进行转换以后才能被Web浏览器所理解,这种处理一般是在软件构建过程中进行的,然后再部署构建后的应用程序。

 

超越HTML的架构

React的基本架构不仅仅适用于在浏览器中渲染HTML。例如,Facebook有动态图表,可以渲染到<canvas>标签,而NetflixPayPal使用通用加载,在服务器和客户端上渲染相同的HTML

 

React Hooks

Hooks是让开发者从函数组件中 "钩入"React状态和生命周期特性的函数。它们使代码具有更强的可读性且更易理解。Hooks并不在类组件内工作,它的终极目标是在React中消除类组件的存在。

 

React提供了一些内置的Hooks,如useStateuseContextuseReduceruseEffect等。它们都在Hooks API参考书中做了说明。使用最多的是useStateuseEffect,分别在React组件中控制状态和检测状态变化。

 

 

Hooks规则

 

Hooks也有一些规则,在使用Hooks之前必须遵循这些规则:

 

l  钩子只能在顶层调用(不能在循环或if语句中调用)。

l  钩子只能在React函数组件中调用,不能在普通函数或类组件中调用。

 

定制Hooks

构建自己的Hooks,也就是所谓的自定义Hooks,可以让你把组件逻辑提取到可重用的函数中。自定义钩子是一个名称以 "use "开头的JavaScript函数,它可以调用其他的钩子。钩子的规则也适用于它们。

 

常用术语

 

React并没有试图提供一个完整的 "应用程序库"。它是专门为构建用户界面而设计的,因此并不包括许多一些开发者认为构建应用程序所需的工具。这使得开发者可以选择任何一个库来完成诸如执行网络访问或本地数据存储等任务。这种情况也就决定了React技术在创建网页应用时标准无法统一。

 

Flux架构的使用

为了支持React的单向数据流的概念(与AngularJS/Angular的双向数据流形成对比),Flux架构是流行的模型-视图-控制器(MVC)架构的具有代表性的替代方案。Flux的特点是,数据动作通过中央调度器发送到一个存储仓库,而对存储仓库数据的变化会被传送回视图。当与React一起使用时,这种传送是通过组件属性完成的。

 

Flux可以被认为是观察者模式的一个变种。

 

Flux架构下的React组件不应该直接修改传递给它的任何props,而是应该传递回调函数,这些回调函数可以创建由调度器发送的数据动作来修改存储仓库。数据动作是一个对象,其职责是描述已经发生的事情:例如,一个数据动作描述的是一个用户 "follow"另一个用户。它可能包含如下数据:

用户ID

目标用户ID

以及USER_FOLLOWED_ANOTHER_USER枚举类型。

存储仓库,是一个数据模型,可以根据从调度器接收到的数据动作来改变自己。

这种模式有时被表述为 "属性向下流动,数据动作向上流动"。自Flux诞生以来,Flux的许多实现被创造出来,其中最著名的是Redux,它的特点是单一的存储仓库,通常被称为单一的数据真相源。

 

历史

React是由Facebook的软件工程师Jordan Walke创建的,受PHPHTML组件库XHP的启发,发布了React的早期原型,名为 "FaxJS",。它于2011年首次部署在FacebookNews Feed上,后来于2012年部署在Instagram上。20135月在美国JSConf大会上开源。

 

React Native20152月在FacebookReact Conf上宣布的,20153月开源的React Native,实现了原生的AndroidiOSUWP开发。

 

2017418日,Facebook宣布了React Fiber,这是React库的一个新的核心算法,用于构建用户界面,React Fiber将成为React库未来任何改进和功能开发的基础。

 

2017926日,React 16.0正式对外发布。

 

2019216日,React 16.8正式对外发布,该版本引入了React Hooks

 

常用命令

 

创建工程:

npx create-react-app my-app

开发环境运行:

npm start

 

生产环境打包:

npm run build

 

【官方网站】

http://reactjs.org/

 

【最新版本】

16.13.12020319

【授权】

MIT License

 

 

Angular

Angular(通常被称为 "Angular 2+" "Angular v2及以上版本")是一个基于TypeScript的开源Web应用框架,由GoogleAngular团队和由个人以及企业组成的社区领导。 Angular是由构建AngularJS的同一个团队从零开始重写的。

 

AngularAngularJS的区别

 

l  Angular没有 "Scope"或控制器的概念,相反,它使用组件的层次结构作为其主要的架构特征。

l  Angular有不同的表达式语法,重点是"[]"用于属性绑定,"() "用于事件绑定

l  模块化 - 许多核心功能已转移到模块上

l  Angular推荐使用微软的TypeScript语言,它引入了以下特性。

n  静态键入,包括Generics

n  注解

l  TypeScriptECMAScript 6 (ES6)的超集,向后兼容ECMAScript 5(即:JavaScript)。

l  动态加载

l  异步模板编译

l  RxJS提供的迭代回调。RxJS限制了状态的可见性和调试,但这些问题可以通过像ngReactngrx这样的反应式附加组件来解决。

l  支持Angular Universal,可以在服务器上运行Angular应用程序。

 

历史

命名

最初,AngularJS的重写被称为 "Angular 2",但这导致了开发人员的迷糊。为了澄清,团队宣布,每个框架使用不同的术语,其中 "AngularJS "指的是1.X版本, "Angular " 指的是2及以上版本。

 

版本2

Angular 2.020141022-23日的ng-Europe大会上宣布。2.0版本的剧烈变化在开发者中引起了相当大的争议。

 

2015430日,Angular开发者宣布Angular 2Alpha转为开发者预览版,201512Angular 2转为Beta版,20165月发布了第一个发布候选版本,2016914日发布了最终版本。

 

版本4

20161213Angular 4发布,跳过了3,避免了因路由器包的版本错位导致的混乱,当时已经发布的版本为v3.3.0。最终版本于2017323日发布,Angular 4向后兼容Angular 2

 

Angular 4.3版本是一个小版本,它是4.x.x版本的替换版本。

 

4.3版本的功能

 

l  介绍了HttpClient,一个更小、更容易使用、更强大的HTTP请求库。

l  为守护者和解析器提供了新的路由器生命周期事件。四个新事件。GuardsCheckStartGuardsCheckEndResolveStartResolveEnd加入了现有的NavigationStart等生命周期事件集。

l  有条件地禁用动画。

 

 

版本5

Angular 52017111日发布,Angular 5的主要改进包括支持渐进式Web应用、构建优化器以及与Material Design相关的改进。

版本6

Angular 6201854日发布。这个版本,关注的重点不在于底层框架,更多的是工具链,以及让Angular在未来的更新和升级更加容易,比如:ngupdateng addAngular元素、Angular Material+CDK组件、Angular Material入门组件、CLI工作区、库支持、树形摇动提供者、动画性能提升、RxJS v6

版本7

Angular 7已于20181018日发布。更新内容涉及到应用性能、Angular Material & CDK、虚拟滚动、Selects的可访问性改进、现在支持自定义元素使用Web标准的内容投影,以及关于Typescript 3.1RxJS 6.3Node 10(仍支持Node 8)的依赖性更新。

版本8

Angular 8已于2019528日发布。具有所有应用代码的差异化加载、惰性路由的动态导入、Web工作者、TypeScript 3.4支持、以及Angular Ivy作为预览版可配置使用。Angular Ivy预览包括:

 

l  生成的代码,在运行时更容易阅读和调试。

l  更快的重建时间

l  减少有效载荷

l  改进了模板类型检查

l  向后兼容

 

版本9

Angular 9已于202026日发布。第9版在默认情况下使用Ivy编译器。Angular可以与TypeScript 3.63.7兼容。除了数百个bug修复之外,Ivy编译器和运行时还提供了许多优势:

 

l  更小的软件包

l  更快的测试

l  更好的调试

l  改进的CSS类和样式绑定

l  改进的类型检查

l  改善了构建错误

l  改善了构建时间,默认开启AOT功能

l  提高国际化功能

 

特点

组件化

一个组件例子

Html部分

 

<h2>Products</h2>

 

<div *ngFor="let product of products">

 

  <h3>

      {{ product.name }}

  </h3>

 

</div>

 

 

Typescript部分

export class ProductListComponent {

  products = products;

}

 

 

路由

 

@NgModule({

  imports: [

    BrowserModule,

    ReactiveFormsModule,

    RouterModule.forRoot([

      { path: ''component: ProductListComponent },

      { path: