1. react 简介
项目地址:https://github.com/MoonHighway/learning-react
官网介绍:React
是一个专注于 UI(View)的 JavaScript
函式库(Library)。若以 MVC
框架来看,React
定位是在 View
的范畴。
React
于 2003 年发布,是一款用于创建用户界面的小型JavaScript
库。React
鼓励用户使用函数式编程升高或面向对象编程。
- 用做 UI: 许多人把
React
当做MVC
设计模式中的视图(view
),当熟练掌握React
的技术之后, 可以将其很轻松应用于一个小功能的项目。 - 虚拟 DOM:
React
用一个”虚拟DOM”实现了超高的性能,配合NodeJS
也可以实现在服务端的渲染,不存在耗时的浏览器dom
渲染。 - 数据流:
React
是一种减少引用数据流的实现方式,并且比传统的方式更容易实现数据绑定。
React
特点
- 声明式设计:
React
采用声明范式,可以轻松描述应用。 - 高效:
React
通过对DOM
的模拟,最大限度地减少与DOM
的交互。 - 灵活:
React
可以与已知的库或框架很好地配合。 - JSX:
JSX
是JavaScript
语法的扩展。React
开发不一定使用JSX
,但官方文档中建议使用它。 - 组件:通过
React
构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。 - 单向响应的数据流:
React
实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
create-react-app
是一个全局的命令行工具用来创建一个新的项目。react-scripts
是一个生成的项目所需要的开发依赖。
为了在浏览器中使用 React
,需要引用两种类库:React
和 ReactDOM
。React
库是用来创建视图的,ReactDOM
库是用来在浏览器中渲染 UI 的。使用方式如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<!-- 以下引入 react.js, react-dom.js(react 0.14 后将 react-dom 从 react 核心分离,更符合 react 跨平台抽象化的定位)以及 babel-core browser 版 -->
<!-- react 使用最新版 CDN 方式引入 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<!-- 这边的 id="example" 的 <div> 为 React Component 要插入的地方 -->
<div id="example"></div>
<!-- 以下就是包在 babel(透过进行语言翻译)中的 React JSX 语法,babel 会将其转为浏览器看的懂得 JavaScript -->
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
上面代码有两个地方需要注意。首先,最后一个 <scrit>
标签的 type
属性为 text/babel
。这是因为 React
独有的 JSX
语法,跟 JavaScript
不兼容。凡是使用 JSX
的地方,都要加上 type="text/babel"
。
其次,上面代码一共用了三个库:react.js
、react-dom.js
和 babel.js
。
react-min.js
:React
的核心库react-dom.min.js
:提供与DOM
相关的功能babel.min.js
:可以将ES6
代码转为ES5
代码,这样我们就能在目前不支持ES6
浏览器上执行React
代码。Babel
内嵌了对JSX
的支持。通过将Babel
和babel-sublime
包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。
react CDN
引用最新版本(直接在 https://cdnjs.com 搜索即可):
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
HTML
只是浏览器构造文档对象模型(DOM
)时执行的一组简单指令。当浏览器载入 HTML
并渲染用户界面时,构成 HTML
文档的元素就是 DOM
元素。
上面我们先简单介绍了 CDN-based
的开发方式让大家先对于 React
有个基本印象,但由于 CDN-based
的开发方式有不少缺点。所以接下来的 Webpack 将会是我们接下来范例的主要使用的开发工具。
Webpack
是一个模组打包工具(module bundler
),以下列出 Webpack
的几项主要功能:
- 将
CSS
、图片与其他资源打包 - 打包之前预处理(
Less、CoffeeScript、JSX、ES6
等)档案 - 依
entry
文件不同,把.js
分拆为多个.js
档案 - 整合丰富的
Loader
可以使用(Webpack
本身仅能处理JavaScript
模组,其余档案如:CSS、Image
需要载入不同Loader
进行处理)
2. ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
总结技巧:在 ReactDOM.render()
中只能由一个 div 或 h1 或 p 等 HTML 标签,并且要在这些标签结尾处加一个逗号如果要想写多个 div 或者 h1 或者 p 标签,可以在外围只写一个 div 标签,然后进行嵌套就可以了,如下面示例代码:
ReactDOM.render(
<div>
<div></div>
<h1></h1>
<p></p>
</div>,
document.getElementById('example')
);
3. JSX 语法
HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX
的语法,它允许 HTML 与 JavaScript 的混写。JSX
是 React
的核心组成部分,它使用 XML
标记的方式去直接声明界面,界面组件之间可以互相嵌套。React
使用 JSX
来替代常规的 JavaScript
。JSX
是一个看起来很像 XML
的 JavaScript
语法扩展。JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 {
开头),就用 JavaScript 规则解析。
JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员:
var arr = [
<h1>Hello world!</h1>,
<h2>React is awesome</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
运行结果如下:
我们不需要一定使用 JSX
,但它有以下优点:
JSX
执行更快,因为它在编译为JavaScript
代码后进行了优化。- 它是类型安全的,在编译过程中就能发现错误。
- 使用
JSX
编写模板更加简单快速。
4. 组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass
方法就用于生成一个组件类。
<script type="text/babel">
class HelloMessage extends React.Component {
render() {
return <h1>Hello {this.props.name}</h1>;
}
}
ReactDOM.render(
<HelloMessage name="Jason" />,
document.getElementById('example')
);
</script>
上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage />
时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。
注意,组件类的第一个字母必须大写,否则会报错,比如 HelloMessage 不能写成 helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。
组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 <HelloMessage name="Jason">
,就是 HelloMessage 组件加入一个 name 属性,值为 Jason。组件的属性可以在组件类的 this.props
对象上获取,比如 name 属性就可以通过 this.props.name
读取。上面代码的运行结果如下。
添加组件属性,有一个地方需要注意,就是 class
属性需要写成 className
,for
属性需要写成 htmlFor
,这是因为 class
和 for
是 JavaScript
的保留字。
5. this.props.children
this.props
对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children
属性。它表示组件的所有子节点。
<script type="text/babel">
class NotesList extends React.Component {
render(){
return (
<ol>
{
React.Children.map(this.props.children, function(child){
return <li>{child}</li>;
})
}
</ol>
);
}
}
</script>
这里需要注意, this.props.children
的值有三种可能:如果当前组件没有子节点,它就是 undefined
;如果有一个子节点,数据类型是 object
;如果有多个子节点,数据类型就是 array
。所以,处理 this.props.children
的时候要小心。React 提供一个工具方法 React.Children
来处理 this.props.children
。我们可以用 React.Children.map
来遍历子节点,而不用担心 this.props.children
的数据类型是 undefined
还是 object
。
6. PropTypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。组件类的 PropTypes
属性,就是用来验证组件实例的属性是否符合要求
.props.children的数据类型是
undefined还是
object`。
6. PropTypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。组件类的 PropTypes
属性,就是用来验证组件实例的属性是否符合要求