目的:构建那些数据会随时间改变的大型应用
对比
和其他一些js框架相比,React怎样,比如Backbone、Angular等。
- React不是一个MVC框架,它是构建易于可重复调用的web组件,侧重于UI, 也就是view层
- 其次React是单向的从数据到视图的渲染,非双向数据绑定
- 不直接操作DOM对象,而是通过虚拟DOM通过diff算法以最小的步骤作用到真实的DOM上。
- 不便于直接操作DOM,大多数时间只是对 virtual DOM 进行编程
所有 React 组件都必须是纯函数,并禁止修改其自身 props 。
React有两个主要的特点
1,简单
简单的表述任意时间点你的应用应该是什么样子的,React将会自动的管理UI界面更新当数据发生变化的时候。
2,声明式
在数据发生变化的时候,React从概念上讲与点击了F5一样,实际上它仅仅是更新了变化的一部分而已。
React是关于构造可重用组件的,实际上,使用React你做的仅仅是构建组建。通过封装,使得组件代码复用、测试以及关注点分离更加容易。
- React不是一个MVC框架
- React不使用模板
- 响应式更新非常简单
- HTML5仅仅是个开始
React主要的原理
Virtual DOM 虚拟DOM
Virtual DOM,一个轻量级的虚拟的DOM,就是React抽象出来的一个对象,描述dom应该什么样子的,应该如何呈现。通过这个Virtual DOM去更新真实的DOM,由这个Virtual DOM管理真实DOM的更新。
React有个diff算法,更新Virtual DOM并不保证马上影响真实的DOM,React会等到事件循环结束,然后利用这个diff算法,通过当前新的dom表述与之前的作比较,计算出最小的步骤更新真实的DOM。
用户在应用中对dom的操作其实是对虚拟dom的操作,用户的操作产生的数据改变或者state变量改变都会保存到虚拟dom上,之后再批量的对这些更改进行diff算法计算,对比操作前后的虚拟dom树,把更改后的变化再同步到真实dom上。
在react虚拟dom机制中,它会把所有的操作都会合并,只会对比刚开始的状态和最后操作的状态,两者中找出不同再同步到真实dom中,这就大大减少了真实dom的操作
Virtual DOM的执行完全都在Javascript 引擎中
Components 组件
在DOM树上的节点被称为元素,在这里则不同,Virtual DOM上称为commponent。Virtual DOM的节点就是一个完整抽象的组件,它是由commponents组成。
JSX
1,JSX 是 JavaScrip 的一种扩展语法,推荐在 React 中使用这种语法来描述 UI 信息。,
3,编译之后,JSX 表达式就变成了常规的 JavaScript 对象。
这意味着你可以在
if
语句或者是
for
循环中使用 JSX,用它给变量赋值,当做参数接收,或者作为函数的返回值
“函数式(Functional)”组件
接收一个
props
参数, 并返回一个 React 元素。
state
私有的,并且由组件本身完全控制
唯一可以分配
this.state
的地方是构造函数constructor
是
类定义
的组件的专有特性
类组件应始终使用
props
调用基础构造函数。
class Clock extends React.Component {
constructor(props) { super(props);
this.state
= {date: new Date()}; }
//
componentDidMount()
钩子在组件输出被渲染到 DOM 之后运行
componentDidMount()
{ this.timerID = setInterval( () => this.tick(), 1000 ); }
//在
componentWillUnmount()
生命周期钩子中取消这个计时器
componentWillUnmount()
{ clearInterval(this.timerID); }
//使用
this.setState()
来来周期性地更新组件本地状态
tick()
{ this.setState({ date: new Date() }); }
render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.
state
.date.toLocaleTimeString()}.</h2> </div> ); }}
2.添加一个名为
render()
的空方法。
3.把原函数中的所有内容移至
render()
中。
4.在
render()
方法中使用
this.props
替代
props
。
5.删除保留的空函数声明。
在一个具有许多组件的应用程序中,在组件被销毁时释放所占用的资源是非常重要的。
键(Keys)
键(Keys) 帮助 React 标识哪个项被修改、添加或者移除了。数组中的每一个元素都应该有一个唯一不变的键(Keys)来标识
keys 只在数组的上下文中存在意义。一个好的经验准则是元素中调用
map()
需要 keys
受控组件(Controlled Components)
在 HTML 中,表单元素如
<input>
,
<textarea>
和
<select>
表单元素通常保持自己的状态,并根据用户输入进行更新。而在 React 中,可变状态一般保存在组件的 state(状态) 属性中,并且只能通过
setState()
更新。
我们可以通过使 React 的 state 成为 “单一数据源原则” 来结合这两个形式。然后渲染表单的 React 组件也可以控制在用户输入之后的行为。这种形式,其值由 React 控制的输入表单元素称为“受控组件”。
状态提升经验总结
在一个 React 应用中,对于任何可变的数据都应该循序“单一数据源”原则。通常情况下,state 首先被添加到需要它进行渲染的组件。然后,如果其它的组件也需要它,你可以提升状态到它们
最近的祖先组件
。你应该依赖
从上到下的数据流向
,而不是试图在不同的组件中同步状态。
提升状态相对于双向绑定方法需要写更多的“模板”代码,但是有一个好处,它可以更方便的找到和隔离 bugs。由于任何 state(状态) 都 “存活” 在若干的组件中,而且可以分别对其独立修改,所以发生错误的可能大大减少。另外,你可以实现任何定制的逻辑来拒绝或者转换用户输入。
编程思想
步骤1:将 UI 拆解到组件层次结构中
步骤2: 用 React 构建一个静态版本
步骤3: 确定 UI state(状态) 的最小(但完整)表示
步骤4:确定 state(状态) 的位置
步骤5:添加反向数据流
确定 UI state(状态) 的最小(但完整)表示
让我们仔细分析每一个数据,弄清楚哪一个是 state(状态) 。请简单地提出有关每个数据的 3 个问题:
- 是否通过 props(属性) 从父级传入? 如果是这样,它可能不是 state(状态) 。
- 是否永远不会发生变化? 如果是这样,它可能不是 state(状态)。
- 是否可以由组件中其他的 state(状态) 或 props(属性) 计算得出?如果是这样,则它不是 state(状态)。
需要确定是哪个组件可变,或者哪个组件
拥有
这些 state(状态)
React 单向数据流在层级中自上而下进行。这样有可能不能立即判断出状态属于哪个组件。
对于你应用中的每一个 state(状态) :
- 确定每个基于这个 state(状态) 渲染的组件。
- 找出公共父级组件(一个单独的组件,在组件层级中位于所有需要这个 state(状态) 的组件的上面。)。
- 公共父级组件 或者 另一个更高级组件拥有这个 state(状态) 。
- 如果找不出一个拥有该 state(状态) 的合适组件,可以创建一个简单的新组件来保留这个 state(状态) ,并将其添加到公共父级组件的上层即可。
