react 学习笔记

React Native提供了哪些能力

  • 基于原生UI组件

  • 手势识别

  • 基于FlexBoxcss布局模式

  • 跨平台开发

  • 基于Reactjsx的组件化开发模式

  • 可使用npm中的模块

  • Chrome Dev Tool的集成

特点:JSX语法,组件化模式,Virtual DOM,单向数据流

基本模式:每个React组件由属性(property)和状态(state)来配置,当状态发生变化时更新UI,组件的结构是由虚拟的DOM来维护,确保了实际更新的DOM只包括真正产生了状态变化的部分


Virtual DOM = UI 虚拟机


首字母大写的是自定义组件,首字母小写的是DOM组件(元素)


JavaScript 代码里写着 XML 格式的代码称为 JSX;或者说可以直接在js中书写HTML代码

上面命令可以将 src 子目录的 js 文件进行语法转换,转码后的文件全部放在 build 子目录。


React允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

var HelloMessage = React.createClass({

render: function() {

return <h1>Hello {this.props.name}</h1>;

}

});



React.render(

<HelloMessage name="John" />,

document.getElementById('example')

);

我们通过 JavaScript 对象传递一些方法到 React.createClass() 来创建一个新的React组件。其中最重要的方法是 render,该方法返回一颗 React 组件树,这棵树最终将会渲染成 HTML


Virtual DOM:相对Browser环境下的DOM(文档对象模型)而言,Virtual DOM是DOM在内存中的一种轻量级表达方式

(原话是lightweight representation of the document),可以通过不同的渲染引擎生成不同平台下的UI,

JS和Native之间通过Bridge通信(React Native通信机制详解 « bang’s blog)。


虚拟 DOM 是躺在内存里的一种特殊的结构,我们可以理解为这是真实 DOM 在内存里的映射。


除了结构上的映射外,这个虚拟的 DOM 还包括了渲染真实所需要的数据以及事件绑定。

虚拟 DOM 在创建时,首先是使用 JSX 的语法生成一个真实 DOM 树的映射,其次是从服务器端拉取远程数据,接着注入到这个虚拟 DOM 树中,同时绑定事件。

接下来,调用 render() 方法一次性渲染出真实的 DOM,然后全量插入到网页中。

虚拟 DOM 静静地躺在内存里,等待数据更新。

新数据来临,调用 setState()方法更新数据到虚拟 DOM 中,然后自动调用 render() 再一次性渲染出真实的 DOM ,然后全量更新到网页中。

一个虚拟 DOM,对应一个真实 DOM

一份数据更新,重新生成虚拟 DOM ,全量更新真实 DOM

React 编写起来,就是编写一个个的组件。

使用 render() 方法生成真实 DOM 并插入到网页中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// 使用 React.createClass 创建一个组件

var DemoComponent = React.createClass({

// 使用 render 方法自动渲染 DOM

render: function () {

return (

<div className="component-hello">

<h1 className="hello-title">Hello React</h1>

<p className="hello-desc">React 初探</p>

<div className="hello-movies">

<p2>我喜欢的电影</p2>

<ul>

<li className="movie-item">

<span className="movie-name">速度与激情7</span>

-

<span className="movie-date">2015</span>

</li>

</ul>

</div>

</div>

)


}

});

// 将组件插入到网页中指定的位置

React.render(<DemoComponent />, document.getElementById('demo'));

第一次渲染真实 DOM 时将使用 getInitialState() 返回的数据。

第二次更新渲染真实 DOM 时将使用 setState() 设置的数据。

在 React 中,数据流是单向的,且组件之间可以嵌套,我们可以通过对最顶层组件传递属性方式,向下层组件传送数据。

JSX 把 JS 和 HTML 糅合起来了,这么理解是不是感觉比较简单:

遇到 {} 包裹的是 JS,遇到 <> 包裹的是 HTML


  • render() 返回的是一系列嵌套的组件this.props 获取父组件传递给子组件的数据 this.setState({data: data});用于动态更新状态,设置数据(设置后UI会自动刷新)


  • getInitialState() 在整个组件的生命周期中只会执行一次,用于初始化数据

操作数据的流程

class 是关键字,改用 className 。组件名大写,不然不被识别

React 会在内存里维护一个代表DOM的结构,调用 render 方法时才生成真正的 DOM 插入到网页中。



要渲染 React 组件,只需创建一个大写字母开头的本地变量。要渲染 HTML 标签,只需在JSX里使用小写字母开头的标签名。

ReactJSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。

react的宽度不支持百分比,设置宽度时不需要带单位 {width: 10},单位其实是pt

总结

  • react 宽度基于pt为单位, 可以通过Dimensions 来获取宽高,PixelRatio 获取密度,如果想使用百分比,可以通过获取屏幕宽度手动计算。
  • 基于flex的布局
view默认宽度为100%

水平居中用alignItems, 垂直居中用justifyContent

基于flex能够实现现有的网格系统需求,且网格能够各种嵌套无bug

Reactjs 笔记

语法糖:不影响功能和使用,增加可读性,从而减少代码出错的机会。

<script type="text/jsx">是必不可少的。需要引入react.js文件和JSXTransform.js文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<script type="text/jsx">

var Hello = React.createClass({

render: function () {

//this表示当前React Components的实例

return <div>Hello {this.props.name}</div>;//这里的<div>和<Hello/>标签统称为React Components

}

}); //React Components

React.render(<Hello name='World' />,//并不是真实存在的DOM标签,通过调用`React.render()`方法呈现最终页面

document.getElementById("container");

);

</script>

render()方法是必须的,当被调用时,它会检查this.propsthis.state并且返回一个单一的子元素。这个子元素可以是

原生DOM组件的虚拟表示(例如<div/>),或者可以是你自定义的复合组件(return())。

React.render():渲染一个 ReactElement 到 DOM 中,放在 container 指定的 DOM 元素下,返回一个到该组件的引用。

  • 参数一:要渲染的React Components

  • 参数二:渲染完成后要插入的容器位置

要渲染 HTML 标签,只需在 JSX里使用小写字母开头的标签名。

1
2
3
4

var myDivElement = <div className="foo" />;

React.render(myDivElement, document.body);

要渲染 React 组件,只需创建一个大写字母开头的本地变量。

1
2
3
4
5
6

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

var myElement = <MyComponent someProperty={true} />;

React.render(myElement, document.body);

React 的 JSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。


ReactDOM.render

ReactDOM.renderReact 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

1
2
3
4

React.render(<h1>Hello, world!</h1>, document.getElementById('example')

);

render里面第二个参数必须使用JavaScript原生的getElementByID方法,不能使用jQuery来选取DOM节点。


HTML语言直接写在JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写


React.createClass 生成一个组件类。组件就是一个 实现预定义接口的JavaScript类:

React.createClass(meta)参数meta是一个实现预定义接口的JavaScript对象,用来 对React组件原型进行扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

var HelloMessage = React.createClass({

render: function() {

return <h1>Hello {this.props.name}</h1>;//React <h1> components的实例,使用 this.props 获得传入组件的数据

}

});



ReactDOM.render(

<HelloMessage name="John" />,//如果这里想放两个,可以用一个div标签包起来

document.getElementById('example')

);

所有组件类都必须有自己的 render方法,用于输出组件。组件的属性可以在组件类的 this.props对象上获取,比如 name 属性就可以通过 this.props.name读取。


HTML5history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。JavaScript是可以通过window.location.hash 读取到的,读取到路径加以解析之后就可以响应不同路径的逻辑处理。

Mounted阶段

React Componentsrender解析生成对应的DOM节点,并被插入浏览器的DOM结构的一个过程

要使用 JavaScript表达式作为属性值,只需把这个表达式用一对大括号 ({}) 包起来,不要用引号 (“”)。

ReactElement的属性有:type,props,keyref。一个 ReactElement 实例是一个轻量的,无状态的,不可变的,虚拟的 DOM 元素 的表示。是一个虚拟 DOM。

组件的生命周期

getInitialState:需要返回一个对象

1
getInitialState 中返回的值将会作为数据的默认值, this.state 用于存储数据

一个组件的生命周期可以理解为三个阶段:

1
2
3
4
5
6

mounting 组件正在插入到 DOM 中

updating 组件正在重新注入新数据后更新到 DOM 中

unmounting 组件从 DOM 中移除

mounting 阶段

1
2
3
4
5
6
7
8

getInitialState() 被调用,返回原始数据

componentWillMount() 在组件 mounting 前调用。当组件要被挂载时这个函数被调用。

componentDidMount() 在组件 mounting 完成后调用。一旦你的组件已经运行了 render 函数,并实际将组件渲染到了 DOM 中,该方法就会被调用。

componentWillUnmount():如果你准备吧组件从 DOM 移除时,这个函数将会被调用。

updating 阶段

1
2
3
4
5
6

componentWillReceiveProps(nextProps) 在接收到新的 props 时调用 shouldComponentUpdate(nextProps, nextState) 在组件需要更新 DOM 时调用,若这个函数返回 false 则告诉 React 不要更新

componentWillUpdate(nextProps, nextState) 在更新发生时调用,可以在这里调用 this.steState() 刷新数据

componentDidUpdate(prevProps, prevState) 在更新完成后调用

unmounting 阶段

componentWillUnmount()在组件移除时被调用,在这里可以对数据进行清理

第一次渲染真实 DOM 时将使用 getInitialState() 返回的数据。

第二次更新渲染真实 DOM 时将使用 setState() 设置的数据。

使用 componentDidMount 在组件初始化后执行一些操作

虚拟DOM元素都是ReactElement

React拿到真实的DOM节点可以通过findDOMNode方法,参数就是React Component

绑定事件可以通过比如onChange={this.changeHandler};来绑定到实例属性上

几个重要方法

  • render() 返回的是一系列嵌套的组件

  • this.props 获取父组件传递给子组件的数据

  • this.setState({data: data}); 用于动态更新状态,设置数据(设置后UI会自动刷新)

  • getInitialState() 在整个组件的生命周期中只会执行一次,用于初始化数据

  • componentDidMount 会在 render 后自动调用,用于异步获取数据,更新数据

只要是一个方法,然后方法里面可以存入复杂数据类型就可以使用大括号,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

React.createClass({

getInitialState:function(){}

})

this.setState({})

render:function(){

return({



})

}

可以把 refs 理解为我们在 HTML 中的id,用于定位到指定的组件。

绑定事件时,我们可以使用 ref="name" 属性对一个 DOM 节点进行标记,同时可以通过 React.findDOMNode(this.refs.name)获取到这个节点的原生 DOM

createElement,创建React组件实例,支持type,config,children三个参数:
this.props.children 属性。它表示组件的所有子节点

使用属性(props):从父组件传入的数据会做为子组件的 属性( property ) ,这些 属性可以通过 this.props 访问到。props 是不可变的:它们从父组件传递过来,“属于”父组件。

this.state 是组件私有的,可以通过调用 this.setState() 来改变它。当 state 更新之后,组件就会重新渲染自己。

我们通过this.state.属性名来访问传入this.setState()里的属性名,从而访问到属性值

render()方法依赖于this.propsthis.state,框架会确保渲染出来的 UI 界面总是与输入(this.propsthis.state

保持一致

生命周期方法,按照时间先后顺序依次为:

1
2

getDefaultProps, getInitialState,componentWillMount, componentDidMount, componentWillReceiveProps,shouldComponentUpdate, componentWillUpdate, componentDidUpdate,componentWillUnmount

事件处理函数的命名

采用 "handle" + "EventName"的方式来命名。

Example:

1
2

<Component onClick={this.handleClick} onLaunchMissiles={this.handleLaunchMissiles} />


组件的三种状态

will 函数在进入状态之前调用,did 函数在进入状态之后调用

获取默认属性,获取初始化状态,组件将要装载,将虚拟DOM转为真实DOM(render),组件已完成装载(componentDidMount,组件已经被渲染到页面上)——执行顺序从上往下


shouldComponentUpdate当组件接收到新属性的时候触发这个函数

销毁阶段只有componentWillUnmount

属性表达式

要使用 JavaScript 表达式作为属性值,只需把这个表达式用一对大括号 ({}) 包起来,不要用引号 (“”)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

<script type="text/jsx">

var Input = React.createClass({

getInitialState: function () {

return {

value: 'hello!'

}

},

handleChange: function (event) {

this.setState({

vaule: event.target.value

})

},

render: function () {

var value = this.state.value;

return(

<div>

<input type="text" value={value} onChange={this.handleChange}/>

<p>{value}</p>

</div>

)


}

});

ReactDOM.render(<Input/>, document.body);

</script>