简介:
各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件。
基于这种方式的一个直观感受就是我们不再需要不厌其烦地来回查找某个 DOM 元素,然后操作 DOM 去更改 UI。
React 大体包含下面这些概念:
- 组件
- JSX
- Virtual DOM
- Data Flow
特点:
-
1.声明式设计 −React采用声明范式,可以轻松描述应用。
-
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
-
3.灵活 −React可以与已知的库或框架很好地配合。
-
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
-
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
-
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单
jsx语法规则:
-
定义虚拟DOM时,不要写引号;
-
标签中混入js表达式时要用{ };
区分: 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方,列 (1) a (2) a+b (3) myFun(1) (4) arr.map() (5) function test() { } 语句(代码): (1) if(){ } (2) for() { } (3) switch() { case:nnn }
-
样式的类名指定不要用class ,要用className;
-
内容样式,要用style={{ key:value }}的形式去写;
-
只有一个根标签;
-
标签必须闭合;
-
标签首字母:
-
(1)若小写字母开头,则将改标签转为html中同名元素,若html中无该标签对应的同名 元素,则报错;
-
(2)若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
组件:
1、函数组件:
function MyComponent(props) {
return <p>函数组件内容</p>
}
2、class类组件:
class MyComponent extends React.Component {
render() {
return <p>类组件内容</p>
}
}
渲染方式:
ReactDom.render(
<MyComponent /> ,
document.getElmentbById('boxId')
)
生命周期:
- 初始阶段:
1、设置组件默认属性:
static defaultProps = { name:'' }
2、设置组件的初始化状态:
constructor() {
super();
this.state = { name:'' }
}
3、componentWillMount():
组件即将被渲染到页面之前触发,适用于发起请求、开启定时器等操作
4、render():
组件渲染
5、componentDidMount():
组件已经被渲染到页面中后触发:此时页面中有了真正的DOM元素,可进行DOM的相关操作;
- 运行中阶段:
1、componentWillReceiveProps():
组件接收到属性时触发
2、shouldComponentUpdate():
当组件接收到新属性,或者组件的状态发生改变时触发,组件首次渲染时不会触发;
该钩子函数可以接收两个参数,新的属性和状态,返回true/false 来控制组件是否需要更新;
一般可以通过该函数来优化性能;
3、componentWillUpdate():
组件即将被更新时触发
4、componentDidUpdate():
组件被更新完成后触发,页面中产生了新的DOM元素,可进行DOM操作
- 销毁阶段:
componentWillUnmount():
组件被销毁时触发,适用与清除定时器,取消Redux的订阅事件等
State:
概念:
State是一个组件的UI数据模型,是组件渲染时的数据依据。状态(state)和属性(props)类似,都是一个组
件所需的数据集合,但是state是私有的,可认为state是组件的“私有属性(或者是局部属性)”
如何判断是否为 State?依据如下:
1、这个变量不是通过Props从父组件中获取;
2、这个变量在组件的整个生命周期中有变化;
3、这个变量不可以通过其它状态(State)或者属性(Props)计算得到;
4、这个变量在render方法中使用。
注意:
并不是组件中所有用到的所有变量都是组件的状态!当存在多个组件共同依赖一个状态时,一般的做法是
状态上移,将这个状态放到这几个组件的公共父组件中。
如何正确使用 State:
一、用setState 修改 State,因为直接修改state,组件并不会重新触发render()
//错误
this.state.name = "小明"
//正确
this.setState({name:"小明"})
二、State的更新是异步的:
1、调用setState后,setState会把要修改的状态放入一个队列中(因此组件的state并不会立刻修改);
2、之后React会优化真正的执行时机来优化性能,所以优化过程中有可能会将多个 setState 的状态修改
合并为一次状态修改,因而state更新可能是异步的;
3、所以不要依赖当前的State,计算下个State
总结:
thus.props 和 this.state 可能是异步更新的,不能依赖他们的值来计算下一个state(状态)
弥补:使用 setState() 的另一种形式,它接受一个函数而不是一个对象。这个函数有两个参数
第一个:是当前最新状态的前一个状态(本次组件状态修改前的状态)
第二个:当前最新的属性props
// 正确
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
//错误
this.setState((prevState, props) => { //没将{}用()括起来,所以会解析成代码块
counter: prevState.counter + props.increment
});
三、State 更新会被合并
根据State类型 更新:
状态的类型,有三种情况:
1、 不可变类型(数字、字符串、布尔值、null、undefined)
直接给要修改的状态赋新的值即可
//原state
this.state = {
name:'小明',
sex:'女'
}
//改变
this.setState({
sex:'男'
})
2、 数组;
3、普通对象(不包含字符串、数组);
总结:数组是一种引用。react 执行 diff算法时比较的是两个引用,而不是引用的对象。直接修改原对象引用值不改变,react 不会重新渲染。因此,修改状态额度数组或对象时,要返回新的数组或对象。
State向下流动:
都说props时组件对外的接口,state是组件对内的接口。一个组件可以选择将state(状态)向下传递,作为其子组件的props(属性)
<MyComponent title={this.state.title}/>
这通常称之为 “从上到下” 或者 “单向” 的数据流、