谈谈 React.js 的核心入门知识

近来React.js变得愈来愈流行,本文就来谈一谈React.js的入门实践,经过分析一些经常使用的概念,以及提供一些入门 的最佳编程编程方式,仅供参考。javascript

首先须要搞懂的是,React并非一个框架,React提供了一些新颖的概念、库 和编程原则让你可以同时在服务端和客户端编写快速、紧凑、漂亮的代码来构建 你的web应用。html

若是你使用React,那么可能会涉及到一些经常使用的概念或技术,包括:java

  • ES6 React
  • 虚拟DOM(virtual DOM)
  • 组件驱动开发(component-driven development)
  • 不变性(immutability)
  • 自上而下的渲染(top-down rendering)
  • 渲染路径和优化
  • 打包工具, ES6, 构建请求, debugging, 路由等
  • 同构React(isomorphic React)

什么是React.js

React.js不是一个框架

在整个Web应用的MVC架构中,你能够将React看做为视图层,而且是一个高效 的视图。React提供了和以往不同的方式来看待视图,它以组件开发为基础。 对React应用而言,你须要分割你的页面,使其成为一个个的组件。也就是说,你的 应用是由这些组件组合而成的。node

你能够经过分割组件的方式去开发复杂的页面或某个功能区块,而且组件是能够 被复用的。这个过程大概相似于用乐高积木去瓶装不一样的物体。咱们称这种编程方式称为 组件驱动开发。react

React的一大特色是其所拥有的虚拟DOM,它让页面渲染变得很是的高效,而且比直接 操纵DOM变得更为可控。这两大特色的组合使得React具备强大的自上而下的页面渲染 能力。webpack

好了,React的有两个特色:组件化和高效的虚拟DOM,可是为何它这么被看好呢? 由于React更多的是一种概念层面的东西,而库是其次的。也有不少其余听从了这些思想的第三方实现。和每个编程概念同样,React尤为 独有的解决方案、工具和工具。但这里并不会深刻的去讨论他们,而是关注React自己。git

Virtual DOM

为了跟踪模型层的变化,而且将其应用到DOM中(也就是渲染),咱们须要注意两个 重要的事情:es6

  1. 数据是何时改变的
  2. 哪个(些)DOM元素须要被更新

对于(1)而言,React提供了一个观察者模型用于替代传统的脏检查(dirty checking), 也就是持续的检查模型的变化。这也就是解释了为何React不须要计算哪些发生 了改变的缘由,由于它会当即知道。这个过程减小了计算量,并它应用程序变得 更平滑。但这里真正有趣的是,React是如何管理DOM操纵的。github

对于DOM改变(2)而言,React在内存中构建了DOM的树形表示,而且计算出哪一个 DOM元素应该被改变。对浏览器而言,DOM操纵是比较耗费性能的,所以咱们更倾向于 让其变得最小化。幸运的是,React视图尽量少的触及到DOM元素。给予对象表示而言, 更少的DOM操纵意味着计算会更快,所以DOM改变也被尽量的减小。web

React在底层实现了一个diffing算法,该算法使用DOM的树形表示法,当某个 节点发生变化(标记为dirty)时它会从新计算整个子树,你会注意到你的模型发生 了改变,由于整个子树在以后会被从新渲染。关于该算法的详细分析能够参考这篇 文章

virtual dom

如何在服务端渲染

由于React在DOM表示时使用了一个虚拟(假的)DOM,所以借助于这种方式使得在服务端 渲染输出HTML称为可能(不借助于JSDom, PhantomJS等)。React还能智能的识别出 服务端渲染出来的页面标记,并在客户端只为这些标记添加事件处理器,这对构建 同构web app很是有用。

有意思的是,React渲染出来的HTML标记都包含了data-reactid属性,这有助于 React中追踪DOM节点。

一些阅读资料

  1. React’s diff algorithm
  2. The Secrets of React’s virtual DOM
  3. Why is React’s concept of virtual DOM said to be more performant than dirty model checking?
  4. virtual-dom

组件驱动开发

对于component-driven development而言,你在一个模板中是看不到整个网站的。 虽然在一开始你可能会遇到一些困难,可是若是进一步的使用这种思路,你会发现 它易于理解,易于维护,而且容易测试。

如何使用React的方式来思考组件开发

下面咱们来看如何实现组件驱动开发这一理念。咱们看一个例子,这个例子来源于 thinking in react 这篇文章。对于构建一个可过滤的产品列表而言,一般其包括以下的组件结构:

  • FilterableProductTable
    • SearchBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow

thinking is react demo

一个组件应该包含什么

首先,理想的,咱们应该遵照单一责任原则 来设计你的组件。当你发下你的组件应该作的更多的时候,你能够考虑将其分割为 更小的组件集合。

由于咱们在讨论组件层级,所以在你的组件中也会使用到其余组件。咱们首先看下 在ES5中组件代码是什么样子的:

var HelloComponent = React.createClass({  
    render: function() {
        return <div>Hello {this.props.name}</div>;
    }
});

 

若是使用ES6,你的组件代码能够这样写:

class HelloComponent extends React.Component {  
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

  

JS和JSX

正如你说看到的,咱们的组件是JS和HTML代码的混合,你可能会以为这很糟糕,由于 MVC一直在教咱们尽量的隔离视图和控制逻辑。但另外一方,这种混合得到另外一个层面的 单一责任,他使得组件更加的灵活和可重用。

固然,在React中你也可使用纯JS来编写你的组件:

render () {
    return React.createElement("div", null, "Hello ",
        this.props.name);
}

  

是的,你会发现这很麻烦,没有使用HTML来得直观。所以React提供了JSX (JavaScript eXtension)语法让你可以在JS中书写HTML代码。

render () {
    return <div>Hello {this.props.name}</div>;
}

 

什么是JSX

JSX在ECMAScript的基础上提供了相似于XML的扩展。 JSX和HTML有点像,但也有不同的地方。例如,HTML中的class属性在JSX中 为className。其余不同的地方,你能够参考FB的 HTML Tags vs. React Components这篇文章。

可是因为浏览器原生并不支持JSX,所以咱们须要将其编译为JS,有不少方法可以 完成这个任务,后面咱们会提到这些方法。此外,Babel也可以讲JSX编译为JS。

一些参考资料:

  1. JSX in depth
  2. Online JSX compiler
  3. Babel: How to use the react transformer

组件还应该包括什么

每一个组件都应该包括一些内部状态,处理逻辑,和事件处理器(例如按钮点击、输入改变), 固然也包括一些内部的样式。

你会遇到{this.props.name}这样的代码片断,这意味着你能够经过属性的方式 先组件内传递数据,例如<MyComp name='weiwei sun' />。这让组件变得可重用, 而且可以自上而下的向嵌套的组件传递数据。

示例代码以下:

class UserName extends React.Component {  
  render() {
    return <div>name: {this.props.name}</div>;
  }
}

class User extends React.Component {  
  render() {
    return <div>
        <h1>City: {this.props.user.city}</h1>
        <UserName name={this.props.user.name} />
      </div>;
  }
}

var user = { name: 'John', city: 'San Francisco' };  
React.render(<User user={user} />, document.body);

 

React拥抱ES6

在React中尝试编写ES6是个很是不错的开始,React并非一开始就支持ES6的, 而是从v0.13.0开始支持的。你会常常用到的ES6特性包括类、箭头函数、consts 和模块。例如,咱们会常常从继承React.Component类开始编写咱们的组件。

还有一点须要注意的是,并非每一个浏览器都支持ES6,所以目前状况下,咱们须要 使用一些工具将咱们编写的ES6代码转换为ES5代码,我推荐使用 Babel

一些参考资料:

  1. Babel: Learn ES6
  2. React ES6 announcement

组件生命周期

每一个React组件在加载时都有特定的生命周期,在此期间不一样的方法会被执行。 下面简单介绍React组件的生命周期:

componentWillMount

该方法会在组件render以前执行,而且永远只执行一次。

componentDidMount

该方法会在组件加载完毕以后当即执行。此时,组件已经完成了DOM结构的渲染, 并能够经过this.getDOMNode()方法来访问。

componentWillReceiveProps

组件接收到一个新的prop时会被执行,且该方法在初始render时不会被调用。

shouldComponentUpdate

在组件接收到新的props或state时被执行。

componentWillUpdate

在组件接收到新的props或者state但尚未render时被执行。 在初始化时不会被执行。

componentDidUpdate

在组件完成更新后当即执行。在初始化时不会被执行。 通常会在组件完成更新后被使用。

componentWillUnMount

在组件从DOM中unmount后当即执行。该方法主要用来执行一些必要的清理任务。

关于生命周期的具体内容,你能够参考官方文档

在打包时使用Webpack和Babel

咱们会常常用到一些工具,首先一个是node.js的模块系统和它的包管理工具npm。 咱们会编写node风格的代码来require咱们须要的东西。而且react自己也是一个独立的 npm包。

一般你有两种选择,commonJS或者ES6:

var React = require('react/addon');

var MyComponent = React.createClass({
    // do something
});

module.exports = MyComponent;

 

或者

import React from 'react/addons';
class MyComponent extends React.Component {
    // do something use es6
}
export default MyComponent;

 

例如,咱们会使用debug模块来调试, 使用superagent模块来编写请求。

如今,咱们有了Node的依赖管理系统,而且使用npm来提供模块。下面咱们须要作的 事:选择一个合适的库来打包咱们的代码,而且可以让其运行在浏览器上。

所以咱们须要一个打包器。目前最流行的解决方案包括两个,分别是Browserify和 Webpack。咱们选择使用Webpack,由于Webpack 更适合于React社区。

Webpack是如何工做的

Webpack用于打包咱们的代码,而且包含进咱们须要的包,而后输出为浏览器可运行的 文件。由于咱们使用JSXES6,所以咱们须要相应的工具来将其转换为ES5。事实上, Babel可以同时作这两件事。使用Webpack可以很轻松的完成这些任务,由于Webpack 是面向配置的。

使用以下命令开始:

npm init
npm install webpack --save-dev
npm install babel --save-dev
npm install babel-loader --save-dev

 

而后建立webpack.config.js文件,咱们须要使用ES5来编写该文件,由于它是 webpack的配置文件。一个典型的配置方式以下:

var path = require('path');

module.exports = {  
  entry: path.resolve(__dirname, '../src/client/scripts/client.js'),
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'bundle.js'
  },

  module: {
    loaders: [
      {
        test: /src\/.+.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      }
    ]
  }
};

 

运行webpack命令你能够执行打包流程。这以后你能够只在页面中包含bundle.js便可。 以下:

<script src='bundle.js'></script>

 

(提示:你可使用node-static来存放你的静态资源文件,使用npm install -g node-static 来安装,并使用static .来启动)。

项目结构

一个典型的项目结构你能够参考这个仓库

config/  
    app.js
    webpack.js (js config over json -> flexible)
src/  
  app/ (the React app: runs on server and client too)
    components/
      __tests__ (Jest test folder)
      AppRoot.jsx
      Cart.jsx
      Item.jsx
    index.js (just to export app)
    app.js
  client/  (only browser: attach app to DOM)
    styles/
    scripts/
      client.js
    index.html
  server/
    index.js
    server.js
.gitignore
.jshintrc
package.json  
README.md

 

如何测试React组件

对于React组件的测试,这里推荐使用Jest, Jest也是由Facebook提供的测试框架,而且有不少强大的特性,但这里并会详细的 介绍它们。

关于Jest,我推荐你阅读和尝试来自Facebook的Tutorial

对于ES6代码的测试,你能够参考 React ES6 Testing

小结

本文简单介绍了React的基础原理,一些相关的编程技术。后续还会整合一些资料 谈一谈Flux和同构。

Statement

本文翻译自:https://blog.risingstack.com/the-react-way-getting-started-tutorial/ 有增删改。

References

  1. https://blog.risingstack.com/the-react-way-getting-started-tutorial/
  2. https://github.com/RisingStack/react-way-getting-started
  3. http://facebook.github.io/react/docs/component-specs.html
相关文章
相关标签/搜索