手把手教你React(1)-React设计思想

1,246 阅读7分钟

前言

React是一个用于构建用户界面的JavaScript库,起源于Facebook开发团队,据说他们对于当时市面上所有的UI库都不满意,于是自己开发了React,并作为Instagram的UI库来使用。由于发现React非常好用,于是Facebook于2013年开源了React。React设计思想属于颠覆性的创新,并且性能出众。发展至今它不再是一个简单UI库,围绕着React已经形成了一整套的行业解决方案,并受到阿里、腾讯等众多中国互联网公司的青睐,作为前端的主流框架使用。

React的特性

在之前提到React的特性我们会说:Just UI、 虚拟dom和单向数据流。这是React面世时提出的三个核心特点,随着时间的发展以及其它UI库的诞生,虚拟dom的广泛应用,并且随着React团队对于React的不断优化,现在React的三个最大特点是声明式、组件化和多端(native、node)渲染。下面我们会一一简单介绍这些特性,并会在后面的文章中详细了解。

1. JUST UI

 React可以认为只是一个模板引擎,使用在任何mv*(mvc,mvvvm等)的框架中做view层,使用react的组件化思想。尽管 React 并没有假设过你的其余技术栈,但它仍可以作为一个小特征轻易地在已有项目中使用。

那么什么是MVC、什么是MVVM它们之间有什么区别,React又是怎么作为view层应用其中呢?

MVC是指Model、View、Controller的模式,而MVVM是指Modal、View、ViewModel。可以看到对于Model和View来说两种模式没有任何区别。Model一般是指数据模型,可以是数据库数据也可以是本地数据,而View就是指视图了。

在MVC模式当中controller是十分重要的一环,它负责从数据库中取出数据并处理渲染到View上,同时当用户进行交互时它也负责获取用户交互内容并处理,进而存储到数据库中,可以看出在MVC模式中,controller承担了巨大的责任。然而,随着项目越来越复杂,尤其是数据解析能力的复杂化,承担巨大责任的controller会变得越来越复杂和臃肿,使其难以维护。

这时,聪明的开发者提出了ViewModel的概念,ViewModel的主要作用就是处理数据解析,以Vue举例(由于Vue特别典型),在Vue体系中,我们可以将Vue的组件实例看做一个VueModel,将组件模板看做View,在引入Vuex等库时完全可以将model抽离出来,形成一个MVVM的模式。在Vue中,实现了一个隐式的binder,将组件实例处理好的数据和View模板进行一个双向的数据绑定。ViewModel将用户行为和视图状态的处理抽象出来,成为可复用的模块,解决了复杂数据处理下Controller的臃肿,和频繁更新dom等问题。

2.虚拟dom

虚拟dom是React提出的一个颠覆性的概念,并且作为重要的基础概念被应用在现代的各个框架之中。虚拟dom是对真实dom进行的一个抽象,将真实的dom抽象成JavaScript对象来描述。虚拟dom的的优势在于以下几点:

1. 快,通过虚拟dom,React使用了diff算法来计算出两次dom变更的最小差异,并且只渲染最小差异变化,同时React会将多次dom操作进行合并并且批量更新,从而提升性能。

2.跨端开发,虚拟dom的另一个重要的好处是实现了跨端开发,由于dom被抽象成了对象,而不是真实的节点,通过该对象我们完全可以描述我们需要渲染的内容,所以我们可以通过虚拟dom渲染native页面(ReactNative、Weex),并且还能讲虚拟dom应用在node,实现服务端渲染。

关于虚拟dom更详细的内容我们会在之后的章节进行讨论。

3.单向数据流

在jquery时代,我们都是基于事件驱动,对于简单的交互需求而言,这确实足够了,而且开发起来非常迅速。但业务一旦复杂,这种基于事件驱动的东西就会变得很乱,页面需要更新的DOM很多,就容易出错。

而在React中数据会从从顶层自上而下的通过props进行传递,复杂的交互操作时,你需要做的,只是更新你的数据源,React会把你的数据从顶层组件一层一层地传下去,React甚至会帮你优化刷新数据时对DOM节点的复用,所以你也无需关注绘制的效率问题。

关于React的数据传递我们也会在后面的文章中进行更详细的阐述。

4.声明式渲染

React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据改变时 React 能有效地更新并正确地渲染组件。

与声明式对应的是命令式,简单来说,命令式是一步步的告诉电脑该怎么做,举个例子

var array = [1,2,3,4,5]

var newArray = []

for(var i = 0; i < array.length; i++) {

  var newNumber = array[i] -1
  newArray.push(newNumber)

}
console.log(newArray)

这是命令式的写法,而声明式的如下:

var array = [1,2,3,4,5]

var newArray = array.map(function(n) {

  return n -1
})
console.log(array)

显而易见,声明式的代码思路更加清晰,更容易维护。

当进行页面渲染时,通过模板和js渲染:

<script id="test" type="text/html">
    <div>
        <h2>北京时间: {{ date.toLocaleTimeString() }}.</h2>
    </div>
</script>

setInterval(function() {
    // 数据
    var data = {
        date: new Date()
    };
    // 渲染(将数据和模板绑定在)
    var html = template('test', data);
    // 渲染
    document.getElementById('container').innerHTML = html;
},100)

通过React声明式渲染:

class Clock extends Component {
  render() {
      return (
          <div>
              <h2>北京时间: { this.props.date.toLocaleTimeString() }</h2>
          </div>
      );
  }
}

setInterval(function() {
    // ReactDOM.render 渲染指令
    ReactDOM.render(
      // date 数据
      <Clock date={new Date()} />,
      document.getElementById('container')
    );
}, 100);

很明显,通过React声明式渲染的组件思路更加清晰,且更易维护。

5. 组件化

创建拥有各自状态的组件,再由这些组件构成更加复杂的 UI。组件逻辑使用 JavaScript 编写而非模版,因此你可以轻松地在应用中传递数据,并使得状态与 DOM 分离。

可以说在React的世界中,一切皆是组件。用户的界面都是由组件拼接而成,并且组件可以组合包裹实现复杂功能,且组件可以实现副作用。

关于组件如何构建,组件的设计思想和组件的组合我们会在之后的文章中更详细的讨论。

6.一次学习,随处编写

无论你现在正在使用什么技术栈,你都可以随时引入 React 来开发新特性,而不需要重写现有代码。

React 还可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。这便是虚拟dom带来的直接好处。

总结:

本文主要介绍了React的主要思想和特点:

1. React专注于View层,并可配合其它库(如Redux, Mobx等)行程MV*架构。

2. React提出了虚拟dom的概念,极大的提高了页面渲染的性能,并能在Native或服务端进行渲染。

3. 单向数据流,React的数据会从上到下的通过props传递,用户只用关心数据状态的更新。

4. React采用声明式渲染,提高代码可读性和可维护性。

5. 组件化,React中组件是一等公民。

在之后的文章中,我们会对React进行更深入的讨论。