微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

【玩转React】关于React你需要知道的事儿

前言

随着前端技术的迅猛发展,各种前端框架也随势崛起,但归根结底,支撑每一款web框架流行的强大因素都是它能更好地服务于业务。React自然也不例外,它的开发者当初正在开发Facebook的一个广告系统,由于不满足于当下任何的MVC框架,所以就自己写了一套UI框架,于是乎大名鼎鼎的React就由此诞生了。React的出现无疑为web开发带来了颠覆性的改变,多少开发者夜以继日只为体验一把React带来的快感。本文就将带领大家一起领略一番React的理念、特色与情怀。

1. React不是一款MVC框架

我们首先要认清的事实就是,React不同于我们之前常用的MVC框架,如AngularJSBackbone等,因为React只专注于view层(即MVC中的V)的表现,它是一个用于构建前端可复用UI组件的库,同时,当数据发生变化时,React会及时有效地更新和渲染相应的组件。对于越来越复杂的前端界面,尤其是对于数据不断变化的web应用,React实现了将变化的数据高效无误的反映在页面上。

下面摘一句React官方doc中的一句话:

We built React to solve one problem: building large applications with data that changes over time.

2. 使用JSX取代HTML模板

JSXReact的核心概念之一,JSX并不是一种新语言,它是对JavaScript语言的扩展,但并没有改变JavaScript的语法,看起来很像XMLJSX使用基于XML的方式表达组件的嵌套,保持和HTML一致的结构,语法上除了在描述组件上比较特别以外,其它基本和Javascript保持一致。 并且最终React会把所有的JSX都编译为JS

我们先来看一个小例子:

var element = <div className="title">
        <h1>Hello World</h1>
    </div>;
ReactDOM.render(element,document.body);

从该例子可以看出,React实现了直接将HTML嵌入到JavaScript中的能力,相信很大一部分人刚接触JSX这种语法时,都心存怀疑,因为多少年我们一直强调MVC,即表现层与逻辑层是要分离的,我们使用HTML模板的目的也是为了避免表现层与逻辑层的耦合。但React使用JSX的这种设计思想,仿佛让我们一夜回到解放前。使用JSX的好处到底是什么呢?

其实,我们最初使用HTML模板的目的是让表现层更加独立,这样对HTML修改就变得更加简单,不需要去看逻辑代码。但如今,web应用已经变得越来越复杂,模板对应的逻辑层代码也是严重依赖于模板DOM结构,这就造成了表现层与逻辑层的严重耦合,最初不看逻辑而简单修改界面的想法也打破了。换句话说,表现层和逻辑层还是互不可分的。而且,为了模板与逻辑的良好合作,还不得不引入很多新概念。我们拿AngularJS举例,使用AngularJS确实从结构上分离了表现层与逻辑层,但是HTML里却混入了大量的标记属性,而且,初学者如果不懂AnjularJS的语法,根本不明白HTML标记属性的寓意何在,由此学习难度与成本也大幅度提升。

说到这儿,我们大概就能体会到React使用JSX的独到之处了。JSX除了使用XML标记的方式去直接声明界面以外,并没有增加其它未知的语法与标记,这不但降低了学习成本,让初学者更快地上手使用React,而且使写出的代码可读性更高,更易于理解。

另外,虽然React推荐使用JSX,但并不是必须的,我们也可以完全使用JavaScript进行开发,但JSX在定义类似HTML的树形结构时,非常简洁明了,下面的例子是不使用JSX和使用JSX开发的对比:

#不使用JSX,重复调用React.createElement方法
React.render(
    React.createElement('div',null,React.createElement('div','Hello World')
        )
    ),document.body
);

#使用JSX,简洁明了的类似HTML树形结构
React.render(
    <div>
        <div>
            <div>Hello World</div>
        </div>
    </div>,document.body
);

所以,有JSX这种好东西,我们有什么理由不用呢?

3. 一切皆组件

组件,即被独立封装的可复用UI部件。组件也是React的核心思想之一。React让我们重新规划界面,把任何一个功能独立的模块都定义成组件。一个个的组件通过不断复用,组合与嵌套等,构成一套完整的UI界面。所以说,使用React开发的界面一切皆为组件。

组件的概念并不难理解,最重要的还是组件之间的交互。React为每个组件都提供一个render方法,这个方法返回组件的实例。组件有两个重要的概念:propsstate,他们的作用都是用于描述组件的状态。props是组件对外交互的接口,是一种父级向子级传递数据的方式;state用于记录组件的不同状态,React把组件看成是一个状态机,通过与用户的交互,实现不同状态,然后重新渲染组件,让UI界面及时有效地随数据变化而变化。

以下是在组件中使用stateprops的应用实例。我们可以在父组件中设置state,并通过在子组件上使用props将其传递到子组件上。

var MainCom = React.createClass({
  getinitialState: function() {
    return {
      message: "Learn React",link: "https://facebook.github.io/react/"
    };
  },render: function() {
    return (
      <div>
        <Message message={this.state.message} />
        <Link link={this.state.link} />
      </div>
    );
  }
});

var Message = React.createClass({
  render: function() {
    return (
      <h1>{this.props.message}</h1>
    );
  }
});

var Link = React.createClass({
  render: function() {
    return (
      <a href={this.props.link}>
        {this.props.link}
      </a>
    );
  }
});

ReactDOM.render(
  <MainCom />,document.getElementById('main-container')
);

组件化的方式带来了UI功能模块之间的分离。对于MVC开发模式来说,开发者将实现表现层,数据层,控制层的分离。对于React而言,则完全是一个新的思路,开发者从功能的角度出发,将UI界面分成不同的组件,每个组件都独立封装。

4. 虚拟DOM提升性能

传统的web开发中,我们通常使用JSjQuery操作DOM的方式将不断变化的数据实时地反映到页面上,随着页面逻辑复杂度的提升,频繁大量的DOM操作往往会造成网站性能较低,代码也变得越来越难维护。即使使用了MVC框架来重新架构代码,但也没有办法减少你所维护的状态,也就是说没有办法减少DOM操作。

后来又出现了MVVM模式,通过视图模板和状态的双向绑定,双向绑定引擎就会在状态更新的时候自动更新视图。MVVM模式很大程度的减少了视图更新的逻辑,即减少了DOM操作。但这种方法也是存在问题的,每次状态发生变化时,模板引擎都会重新渲染整个视图,即用新的视图替换掉旧的视图。我们知道,这样做是影响性能的,因为即使一处小小的修改都会引起重新渲染DOM。

React的思想里,是完全不需要操作DOM的。React提出了新概念,即虚拟DOM。使用React进行开发时,所有的DOM构造都是通过虚拟DOM进行的,每当数据发生变化时,React都会重新构造DOM树,然后将新构造的DOM树与上一次的DOM树进行对比(这就用到了React的DOM Diff算法),得到两者之间的差异后,仅需将变化的DOM部分进行更新。由于每次生成虚拟DOM都很快,DOM Diff算法找出两个DOM树之间的差异也很快(时间复杂度O(n)),所以跟传统的操作DOM相比,使用虚拟DOM方法在速度和性能上的优势是十分明显的。

我们举一个简单的例子,假设我们有一个list如下:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

现在想把它更新成:

<ul>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
</ul>

我们传统的做法是先删除1,2,3,4这些节点,然后再追加6,7,8,9,10这几个新节点,这就意味这会有4次删除操作和5次添加操作。但React会把旧的和新的DOM树做一下Diff,然后发现其实不用删除1,2,3,4节点,而是可以直接修改这四个节点的innerHTML为6,7,8,9,然后再追加一个节点10就可以了。这样就比9次节点DOM操作快多了。

5. 总结

本文只是个人对React的设计思想的一些浅显的认识,写的比较零散,当然React的优点还有很多的,还待大家去慢慢学习与体会。当然,事物都有相对性,在实际的开发过程中,还是要挑选最适合的框架,而不是盲目从众。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...