React
优势:
Virtual DOM
- VD 是一个 obj 结构, 能够反映出对应的 DOM 节点内容, 下面是一个根据 dom 转译出来的 VD
<div>
Hello World
<ul>
<li id="1" class="li-1">
第1
</li>
</ul>
</div>
{
tag: "div",
props: {},
children: [
"Hello World",
{
tag: "ul",
props: {},
children: [{
tag: "li",
props: {
id: 1,
class: "li-1"
},
children: ["第", 1]
}]
}
]
}
diff 算法
有状态, 无状态组件
- 有状态组件:
class类型的组件有state数据, 没有生命周期函数, 有props - 无状态组件:
function类型的组件, 没有state数据, 有生命周期函数, 有props
React 与 Babel
jsx 来自于用户自定义的 render 方法里面
- jsx 是 js 的扩展, 和 模版语言 ` ` 很接近
- 一个看着很像
HTML的 语法糖, 其实质还是会 babel 编译之后的 js 代码 - jsx 不会天然的被支持 js 支持, 而需要用 babel 去编译
React.createElement()
createElement(): Babel 转译 jsx 是通过 createElement() 的方法
- 以对象形式传入, 主要用来格式化数据,没有其他复杂数据, 并返回
ReactElement()
ReactElement() : 数据组装, 生成虚拟 DOM 树
- 主要是用来组装数据
- 里面有虚拟 DOM
- 会扔到
ReactDOM.render()方法之中
ReactDOM.render() : 虚拟 DOM => 真实 DOM
生命周期
- 每个组件(渲染),每个组件都是自己内部单独的
- 每个组件的关联只有数据的关联
渲染工作流
- 组件数据改变 => 组件实际更新
Mounting(挂载)阶段
-
constructor()只触发一次
-
componentWillMount()只触发一次
-
render()并不会去操作真实 DOM, 他的职责是把需要渲染出来的内容返回出来. (操作真实的 DOM 不是
render(), 而是ReactDOM.render()) -
componentDidMount()在渲染结束之后被触发, 真实 DOM 已经挂载了页面上, 可以在这个生命周期里面执行真实的 DOM 相关的操作
Updating(挂载)阶段
由父组件触发,或者组件自身通过 setState()方法触发
componentWillReceiveProps()
- 只由父组件调用更新的时候触发, 组件自身更新(通过
setState()调用)不触发 - 如果父组件导致组件重新渲染,即使
props没有更改, 也会调用此方法, 如果处理更改, 请确保当前值与变更值得比较. 也就是说只要父组件发生了更新, 这个方法就必然会调用, 当然子组件更不更新另说, 但是这个方法一定会被调用
shouldComponentUpdate(nextProps, nextState)
- 组件是否应该执行更新, 返回
boolean, 如果返回是true那么就会更新, 否则不更新 - 可以利用参数,来确定是否应该更新组件
componentWillUpdate()
- 已经不怎么使用了
render()
- update 阶段会再次触发
render()
componentDidUpdate( preProps, preState)
- 组件完成更新后调用, 可以在这里面去操作 DOM
- 可以接受两个参数 一个是 preProps 和 preState
- 典型用法: 如果前后两次的 id 不一样, 可以从新发送 Http 请求
Unmounting 阶段: 组件的卸载
componentWillUnmount()
- 组件在父组件中一处
- 组件设置了 key 属性, 父组件在 render 的过程中,发现 key 值和上一次不一致,就会触发这个方法
受控组件与非受控组件
- 受控组件:以
表单,input等需要输入值得组件, 都受react 的state来控制内容和值, 都叫做受控组件. 这里面值统一都由 react 来管理 - 非受控组件 : 不由 react 去管理
input和表单里面的内容,而是由 dom 自身节点自己控制自己.ref经常用到,来取 dom 里面存储的值
Redux
Redux 应该用来储存各个页面之间的共享数据, 例如: 登录数据, 购物车数据
Redux 不应该过于庞大, 各个页面的自身所有的数据,应该保存在各个页面自身当中
store
- 存储仓库, 用来触发 reducer 去修改自身的值, 从而影响 component 的展示
store.subscribe( function A)
- 时时刻刻去监听 functionA, 如果 functionA 发生变化, 那么 store 就会随之会产生对应的响应事件
reducer
- 其实就是方法, 用来修改值
action
React-Redux (主要使用)
- 核心思想就是把 store 给传递个需要 store 的子组件. 这样就不需要重新走 render 方法更新所有的组件, 只需要更新需要 store 的组件就可以了
Provider能够把 store 传递给 Provider 里面包裹的组件, 把 store 给应用到子组件的实例中connect能够将组件连接到 store 的功能, 接收 store 传过来的东西, 可以利用装饰器
import React, { Component } from "react";
import { Button } from "antd";
import { connect } from "react-redux";
// 该方法是把 我们的 state 给包装成组件的 props
const mapStateToProps = (state) => {
return {
num: state,
};
};
// 该方法是把我们的 dispatch 动作给包装成 props
const mapDispatchToProps = (dispatch) => {
return {
increment: () => {import React, { Component } from "react";
import { Button } from "antd";
import { connect } from "react-redux";
// 该方法是把 我们的 state 给包装成组件的 props
const mapStateToProps = (state) => {
return {
num: state,
};
};
// 该方法是把我们的 dispatch 动作给包装成 props
// 来触发 reducer
const mapDispatchToProps = (dispatch) => {
return {
increment: () => {
dispatch({ type: "INCREMENT" });
},
decrement: () => {
dispatch({ type: "DECREMENT" });
},
};
};
// 装饰器原理
@connect(mapStateToProps, mapDispatchToProps)
class ReduxTest extends Component {
render() {
return (
<div>
<h3>{this.props.num}</h3>
<Button type='success' onClick={() => this.props.increment()}>
+1
</Button>
<Button type='success' onClick={() => this.props.decrement()}>
-1
</Button>
</div>
);
}
}
export default ReduxTest;
dispatch({ type: "INCREMENT" });
},
decrement: () => {
dispatch({ type: "DECREMENT" });
},
};
};
@connect(mapStateToProps, mapDispatchToProps) // 装饰器
class ReduxTest extends Component {
render() {
return (
<div>
<h3>{this.props.num}</h3>
<Button type='success' onClick={() => this.props.increment()}>
+1
</Button>
<Button type='success' onClick={() => this.props.decrement()}>
-1
</Button>
</div>
);
}
}
export default ReduxTest;
Redux 中间件
- 应用在 store 当中
- 中间件定义: 在通过action 去 dispatch 触发 reducer 修改 state 之前, 可以加一些其他的流程,就是中间件
- redux-thunk : 处理异步 action
- redux-logger: 处理日志记录的中间件
Mobx (React+ Mobx更适合中小型项目)
- Mobx 是一个提供者, 用于存储和更新状态 state
react-router-dom
常用的组件有 Link, Route, Redirect, Switch, BrowserRouter, HashRouter
- Redirect : 重定向组件, 如果没有匹配的 path 那么就会自动走 Redirect 中的
to中所指定的路径 - Link: 导航组件
- Route: 路由定义, 定义不同的 path da
dva
- 把 react-redux 和 react-thunk 等一些数据控制的进行了整合
- dva 中的数据流向, 基本上与 react-redux 一致
数据改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转)触发的, 当此类行为改变数据的时候, 可以通过
dispatch发一个action, 如果是同步行为会直接通过reducer改变state, 如果是异步行为,会先出法副作用(effect), 然后流向Reducer最终改变state, 所以在 dva 中,数据也是跟redux一致的, 单向流