虚拟DOM、状态、单向数据流
react 特点
-
声明式的视图层
基于状态声明(JSX)
-
简单的更新流程
状态 =》 UI,单向数据流
-
灵活的渲染实现:
React并不是把视图直接渲染成最终的终端界面, 而是先把它们渲染成虚拟DOM。 虚拟DOM只是普通的JavaScript对象, 可以结合其他依赖库把这个对象渲染成不同终端上的UI
-
高效的DOM操作
基于React的diff算法,操作虚拟DOM(JavaScript对象),并且减少 渲染次数
注:React属于MVC中V这一层
JSX
- JSX 是一种用于描述UI的JavaScript扩展语法,React使用这种语法描述组件的UI;
- DOM类型标签,首字母小写;React组件类标签,首字母大写
两者可以嵌套使用
-
JavaScript表达式
使用场景: - 通过表达式给标签属性赋值 - 通过表达式定义子组件
// 通过表达式给标签属性赋值 const element = <Mycomponent foo={ 1 + 2 } /> // 通过表达式定义子组件(map虽然是函数,但它的返回值是JavaScript表达 式) const todos = ['item1', 'item2', 'item3']; const element = ( <ul> { todos.map(message => <Item key={message} message= {message} />) } </ul> ); 注: JSX中只能使用JavaScript表达式,而不能使用多行JavaScript 语句
-
标签属性
class --> className onclick ---> onClick
-
注释
{/* 注释写在这里 */}
组件
-
组件定义
两种方式: - 使用 ES6 class: -- 1、class继承自React.Component -- 2、class内部必须定义render方法,render方法必须返回代表 该UI组件的React元素 - 使用函数
-
组件的props
组建的props用于把父组件的数据或者方法传递给子组件,是一个简单 结构的对象,如: <User name='react' age='4' address='china' /> props = { name: 'react', age: '4, address: 'china' }
-
组件的state
state是组件内部的状态,state的变化最终反映到组件UI的变化上。 我们在组件的构造方法constructor中通过this.state定义组件的初 始状态,并通过调用this.setState方法改变组件状态(也是改变组件状态 的唯一方式),进而组件UI也会随之重新渲染。
-
props与state
React组件正是由props和state两种类型的数据驱动渲染出组件UI。 props是组件对外的接口,组件通过props接收外部传入的数据(包括方 法);state是组件对内的接口,组件内部状态的变化通过state来反映。 另外,props是只读的,你不能在组件内部修改props;state是可变的, 组件状态的变化通过修改state来实现
-
函数式定义组件
function welcome(props) { return <h1>hello, {props.name}</h1> }
-
组件的生命周期
三个阶段: 挂载阶段、更新阶段、销毁阶段
-
挂载阶段
1、 constructor 2、 componentWillMount 3、 render 4、 componentDidMount
- constructor:组件的构造方法,接收props参数;
(通常用于初始化组件的state及绑定事件处理方法等工作) - componentWillMount:组件挂载到DOM前调用,且只会调用一次;
(很少用到: 在这个方法内调用this.setState不会引起组件的重新渲染) - render: 定义组件时唯一必要的方法(其他生命周期方法都可省略),不负责组件的实际渲染工作,
只是返回一个UI的描述。在render中不能执行setState。 - componentDidMount:在组件被挂载到DOM后调用,且只会被调用一次。这时候已经可
以获取到DOM结构,因此依赖DOM节点的操作可以放到这个方法中。这个方法通常还会用于向服务器端请求数据。在这个方法中调用
this.setState会引起组件的重新渲染
- constructor:组件的构造方法,接收props参数;
-
更新阶段
1、componentWillReceiveProps(nextProps): 通过对比props决定是否改变state 2、shouldComponentUpdate(nextProps,nextState): 返回true继续执行,返回false,不执行 3、componentWillUpdate(nextProps, nextState):与shouldComponentUpdate都不能调用setState 4、render 5、componentDidUpdate(prevProps, prevState):组件更新后被调用,可以作为操作更新后的DOM的地方。这个方 法的两个参数prevProps、prevState代表组件更新前的props和state。
-
卸载阶段
1、componentWillUnmount
-
深入组件
-
组件state
- 组件的任何UI改变都可以从state的变化反映出来
- state中的所有状态都用于反映组件UI的变化,没有多余的状态,也不应该存在可以通过其他状态计算而来的中间状态
修改state: 1、不能直接修改,用setState() 2、state的更新是异步的,setState是把要修改的状态放入一个队列中,所以不能依赖当前的state,计算下一个state (props的更新也是异步的)
-
组件与不可变对象
- 状态的类型是不可变类型(number、string、boolean、null、undefined)
- 状态的类型是数组
// 方法一:使用preState、concat创建新数组 this.setState(preState => ({ books: preState.books.concat(['React Guide']); })) // 方法二:ES6 spread syntax this.setState(preState => ({ books: [...preState.books, 'React Guide']; }))
- 状态的类型是普通对象(不包含字符串、数组)
(1)使用ES6的Object.assgin方法: this.setState(preState => ({ owner: Object.assign({}, preState.owner, {name: 'Jason'}); })) (2)使用对象扩展语法(object spread properties): this.setState(preState => ({ owner: {...preState.owner, name: 'Jason'}; })) ```