[关闭]
@tsingwong 2016-10-13T08:28:36.000000Z 字数 6921 阅读 902

React 学习记录

React



简介

如今,Web 开发朝着 组件化 的趋势发展。主要有现今比较流行的AngularJS和React为代表。

假如,HTML是一个轮子,AngularJS的组件化是给轮子加了个金边;而React是重新造了个轮子JSX

由于HTML的DOM操作非常消耗资源,React引入了虚拟DOM。开发人员操作虚拟DOM,React在必要的时候将它们渲染到真正的DOM上。比较类似游戏开发中,使用的双缓冲区帧重绘。

引入虚拟DOM的另一个好处是,容易引入不同的渲染引擎。例如,将应用代码渲染到HTML的DOM,或者nodejs服务端的无头DOM(这个地方不清楚什么意思,等以后看了nodejs之后再来填坑吧), 还有就是IOS/Android平台组件——即React Native

Hello React!

引入React库之后,就可以通过React对象来操作。即:在虚拟DOM上创建元素,然后将他们渲染到真实DOM上。

createElement(type, [props], [children...]): 在虚拟DOM上创建指定的React元素

render(element, container, [callbcak]):将虚拟DOM上的对象渲染到真实DOM上。

  1. <div id="example"></div>
  2. <script type="text/babel">
  3. var el = React.createElement(
  4. "ul",
  5. null,
  6. React.createElement("li", null, "China"),
  7. React.createElement("li", null, "Japan"),
  8. React.createElement("li", null, "Korea")
  9. );
  10. ReactDOM.render(el, document.querySelector('#example'), alert('Hello World!'));
  11. </script>

上面的例子是在虚拟DOM中创建了一个具有三个li子元素的ul元素,然后将虚拟DOM上的元素渲染到真实DOM上的example容器里。

虚拟DOM

虚拟DOM是React的基石。

在React中,应用程序在虚拟DOM上操作,每次需要渲染的时候,会先比较当前DOM和待渲染内容的差异,然后再决定如何最优的更新DOM,该过程被称为 reconciliation

除此之外,虚拟DOM还可以提供一致的开发方式来开发服务器端应用、Web应用和手机应用。通过虚拟DOM,配置不同的渲染器,将虚拟DOM内容渲染到不同的平台上。

此处输入图片的描述

React 组件

组件的设计目的是提高代码复用率降低测试难度代码复杂度

在React中定义一个组件非常容易。组件就是一个实现预定义接口的JavaScript类。

组件的基本形式是:

  1. React.createClass(meta)

参数meta:一个实现预定义接口的JavaScript对象,用来对React组件原型进行拓展。至少需要一个实现render()方法,而这个方法,必须且只能返回一个有效的React元素。

若组件由多个元素构成,那么必须在外边包一个顶层元素,然后返回这个顶层元素。如:

  1. render:function(){
  2. return React.createElement(
  3. "div",null,
  4. React.createElement("div",null,"header"),
  5. React.createElement("div",null,"content"),
  6. React.createElement("div",null,"footer"),
  7. React.createElement("div",{className: "ez-led"},"footer2")
  8. );
  9. }

注:React组件名称的首字母必须大写。还有一点是class属性使用className代替,for属性使用htmlFor代替。因为class和for是JavaScript的保留字。

组件的生命周期

组件本质上是状态机,输入确定,输出一定确定。
状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出相应。

组件生命周期分为三个状态:

React分别为每个状态提供了两种处理函数。will函数在进入状态之前调用,did函数在进入状态之后调用,三种状态共计五种处理函数。

  1. componentWillMount()
  2. componentDidMount()
  3. componentWillUpdate(object nextProps, object nextState)
  4. componentDidUpdate(object preProps, object prevState)
  5. componentWillUnmount()

此外还有两种特殊状态的处理函数

  1. // 已加载组件收到新的参数时调用
  2. componentWillReceiveProps(object nextProps)
  3. // 组件判断是否重新渲染时调用
  4. shouldComponentUpdate(object nextProps, object nextState)

初始化

初始化阶段有以下五个钩子函数:

运行中

运行中阶段有以下五个钩子函数:

销毁

销毁阶段有一个钩子函数:

JSX

JSX(JavaScript XML),是对JavaScript语法的拓展,它有助于在JavaScript代码中以类似HTML的形式创建React元素。

JSX有以下特点:

简单说,就是每当你需要使用createElement()时,就可以把这个函数调用部分用渲染目标HTML代替(如同上面提到的,这里的class属性仍然需要使用className):

  1. var Comp = React.creatClass({
  2. render: function() {
  3. var e =
  4. <div>
  5. <div className="ez-led">Hello React!</div>
  6. <div className="ez-led">React Hello!</div>
  7. </div>;
  8. retrun e;
  9. };
  10. });
  11. ReactDOM.render(
  12. <Comp />,
  13. document.querySelector("#content")
  14. );

JSX语法:

JSX中不能使用if语句,于是有四种方法来代替:

JSX引入三个非DOM属性:dangerouselySetInnerHTMLrefkey

dangerouselySetInnerHTML:在JSX中直接插入HTML代码
ref:父组件引用子组件
key:提高渲染性能(diff算法)

diff算法流程:
1. 节点是否相同?不同直接结束使用新节点,相同的话继续;
2. 是否为自定义节点?不是的话比较属性,增加新属性;是自定义节点,重新渲染,比较结果。

JSX的引用方法与JavaScript略有不同:
1.指定脚本类型

  1. // 内联
  2. <script type="text/jsx">...</script>
  3. // 外联
  4. <script type="text/js" src="a.js"></script>

2.引入JSX语法转换库
在HTML中使用JSX,还需要引入JSX语法转换库JSXTransform.js。该库加载之后,将在DOM树构造完成后(通过监听DOMContentLoaded事件)处理JSX脚本:

  1. 1. 搜索DOM树中的script节点,类型为text/jsx进行后续处理
  2. 2. 读取script节点的内容,将其转化成JavaScript代码
  3. 3. 构造一个新的script元素,设置其内容为转化后的代码,并追加到DOMhead元素中

JSXTransform.js引入后通过全局对象JSXTranformer提供了API接口,可以使用transform()方法来模拟这个语法自动转换过程。

  1. <script type="text/javascript">
  2. // 模拟JSX语法转换
  3. var transform = function() {
  4. var el =document.querySelector("#demo"),
  5. // 将原始JSX代码转化为JS代码
  6. jsxt = JSXTransformer.transform(el.text);
  7. var headEl = document.querySelector("head"),
  8. scriptEl = document.createElement("script");
  9. // 设置新的script元素的内容为转换后的代码
  10. scriptEl.text = jsxt.code;
  11. scriptEl.type = "text/javascript";
  12. // 将新的script元素添加到文档的head元素
  13. headEl.appendChild(scriptEl);

这里需要提到的一点是<script type="text/jsx"></script><script type="text/jsx"></script>
前者需要使用其自身用于JSX语法解析的编译器jSTransform
后者需要第三方Babel的JSX编译器实现。
React官方在2015年6月发布声明,不再维护jSTransform,所以建议还是都使用后者。

属性与状态

属性

props = properties
属性:一个事物的性质与关系,往往与生俱来,无法自己修改的。
一般是由父组件传递过来的,想当于出生就具有的,但无法自己修改。

属性用法:

  1. 1. 传入键值对,值可以是字符串,或是用{}包裹的JS求值表达式、数组、变量等
  2. <HelloWorld name="tsingwong"></HelloWorld>
  3. 2. 传入"..."+对象,自动将对象中的属性和值当做属性赋值
  4. var props = {
  5. one: "123",
  6. two:321
  7. }
  8. <HelloWorld {...props}></HelloWorld>
  9. 3. 调用React提供的setProps方法设置属性,实际中不提倡使用,一般不会在组件内部修改属性
  10. var instance = React.render(<HelloWorld></HelloWorld>,
  11. document.getElementById("example");
  12. instance.setProps({name: "Tim"});

状态

state
状态:事物所处的状况
状态是由事物自行处理、不断变化的。

状态用法:

  1. getInitialStateP: 初始化每个实例特有的状态
  2. setState:更新组件状态

属性与状态对比

相似点:
1. 都是纯JS对象;
2. 都会触发render更新;
3. 都具有确定性。

属性状态对比 属性 状态
能否从父组件获取初始值? X
能否由父组件修改? X
能否在组件内部设置默认值?
能否在组件内部修改? X
能否设置自组件的初始值? X
能否修改子组件的值 X

注:便于记忆,状态只跟自己相关,由自己维护;组件不能修改属性

区分属性和状态

组件在运行时需要修改的数据是状态。

事件

事件处理函数

事件处理函数主要分为两种

事件处理函数绑定到事件上

  1. onClick={this.handleClick}
  1. 触摸类事件,仅在移动端触发:
  2. - onTouchCancel
  3. - onTouchEnd
  4. - onTouchMove
  5. - onTouchStart
  6. 键盘类事件:
  7. - onKeyDown
  8. - onKeyPress
  9. - onKeyUp
  10. 剪切类事件:
  11. - onCopy
  12. - onCut
  13. - onPaste
  14. 表单类事件:
  15. - onChange
  16. - onInput
  17. - onSubmit
  18. 焦点类事件:
  19. - onFoucs
  20. - onBlur
  21. UI元素类事件:
  22. - onScroll
  23. 滚轮事件:
  24. - onWheel
  25. 鼠标事件:
  26. - onClick
  27. - onContextMenu:右键——即上下文菜单
  28. - onDoubleClick
  29. - onMouseDown
  30. - onMouseEnter
  31. - onMouseLeave
  32. - onMouseMove
  33. - onMouseOut
  34. - onMouseOver
  35. - onMouseUp

事件对象

  1. handleChange: function(event) {
  2. console.log(event.target.value);
  3. }

组件协同使用

组件协同本质上是对组件的一种组织、管理方法。
目的:

方法:
1. 组件嵌套: 在垂直方向上,由下至上的提取——代码的封装
2. Mixin:在水平方向上抽离——代码的复用

组件嵌套

组件嵌套的本质是父子关系。

间接双向通信
父组件传递属性给子组件,
子组件以父组件的事件处理函数,子组件触发父组件函数(委托)

组件嵌套优点:

组件嵌套缺点:

Mixin

Mixin = 一组方法
Mixin的目的是横向抽离出组件的相似代码
相关概念:面向切面编程、插件

Mixin优点:

Mixin缺点:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注