近来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
- 数据是何时改变的
- 哪个(些)DOM元素须要被更新
对于(1)而言,React提供了一个观察者模型用于替代传统的脏检查(dirty checking), 也就是持续的检查模型的变化。这也就是解释了为何React不须要计算哪些发生 了改变的缘由,由于它会当即知道。这个过程减小了计算量,并它应用程序变得 更平滑。但这里真正有趣的是,React是如何管理DOM操纵的。github
对于DOM改变(2)而言,React在内存中构建了DOM的树形表示,而且计算出哪一个 DOM元素应该被改变。对浏览器而言,DOM操纵是比较耗费性能的,所以咱们更倾向于 让其变得最小化。幸运的是,React视图尽量少的触及到DOM元素。给予对象表示而言, 更少的DOM操纵意味着计算会更快,所以DOM改变也被尽量的减小。web
React在底层实现了一个diffing
算法,该算法使用DOM的树形表示法,当某个 节点发生变化(标记为dirty)时它会从新计算整个子树,你会注意到你的模型发生 了改变,由于整个子树在以后会被从新渲染。关于该算法的详细分析能够参考这篇 文章。
如何在服务端渲染
由于React在DOM表示时使用了一个虚拟(假的)DOM,所以借助于这种方式使得在服务端 渲染输出HTML称为可能(不借助于JSDom, PhantomJS等)。React还能智能的识别出 服务端渲染出来的页面标记,并在客户端只为这些标记添加事件处理器,这对构建 同构web app很是有用。
有意思的是,React渲染出来的HTML标记都包含了data-reactid
属性,这有助于 React中追踪DOM节点。
一些阅读资料
- React’s diff algorithm
- The Secrets of React’s virtual DOM
- Why is React’s concept of virtual DOM said to be more performant than dirty model checking?
- virtual-dom
组件驱动开发
对于component-driven development而言,你在一个模板中是看不到整个网站的。 虽然在一开始你可能会遇到一些困难,可是若是进一步的使用这种思路,你会发现 它易于理解,易于维护,而且容易测试。
如何使用React的方式来思考组件开发
下面咱们来看如何实现组件驱动开发这一理念。咱们看一个例子,这个例子来源于 thinking in react 这篇文章。对于构建一个可过滤的产品列表而言,一般其包括以下的组件结构:
- FilterableProductTable
- SearchBar
- ProductTable
- ProductCategoryRow
- ProductRow
一个组件应该包含什么
首先,理想的,咱们应该遵照单一责任原则 来设计你的组件。当你发下你的组件应该作的更多的时候,你能够考虑将其分割为 更小的组件集合。
由于咱们在讨论组件层级,所以在你的组件中也会使用到其余组件。咱们首先看下 在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。
一些参考资料:
组件还应该包括什么
每一个组件都应该包括一些内部状态,处理逻辑,和事件处理器(例如按钮点击、输入改变), 固然也包括一些内部的样式。
你会遇到{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。
一些参考资料:
组件生命周期
每一个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用于打包咱们的代码,而且包含进咱们须要的包,而后输出为浏览器可运行的 文件。由于咱们使用JSX
和ES6
,所以咱们须要相应的工具来将其转换为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
- https://blog.risingstack.com/the-react-way-getting-started-tutorial/
- https://github.com/RisingStack/react-way-getting-started
- http://facebook.github.io/react/docs/component-specs.html