React
定义:
React 是一个用于构建用户界面的 JAVASCRIPT 库。
React主要用于构建UI,React 被认为是 MVC 中的 V(视图)。
特点:
声明式设计 −React采用声明范式,可以轻松描述应用。
高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
灵活 −React可以与已知的库或框架很好地配合。
JSX − JSX 是 JavaScript 语法的扩展
组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
为什么需要Redux?
React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两个方面,react没有涉及:
代码结构
组件之间的通信
React 能够根据 state 的变化来更新 view,setState 方法用于改变组件当前的 state,所以可以把更改 state 的逻辑写在各自的组件里,但这样做的问题在于,当项目逻辑变得越来越复杂的时候,将很难理清 state 跟 view 之间的对应关系(一个 state 的变化可能引起多个 view 的变化,一个 view 上面触发的事件可能引起多个 state 的改变)。我们需要对所有引起 state 变化的情况进行统一管理,这种情况下,就可能需要用到redux了。
简单说,React的核心是使用组件定义界面的表现,那么在使用React的时候我们通常还需要一套机制去管理组件与组件之间,组件与数据模型之间的通信。
Redux
核心概念:
-
Store
作用:保存数据的地方,用于管理整个应用的数据。它实际上是一个Object tree
,整个应用只能有一个Store
。产生:传入
reducer
和可选的初始state
值,通过createStore
方法生成const store = createStore(reducer,initialState)
-
Action
作用:描述用户的行为,也就是View
发出的通知,被store
接收
产生:通过action creator
产生const ADD_TODO = '添加 TODO'; function addTodo(text) { return { type: ADD_TODO,text } } const action = addTodo('Learn Redux')
-
Reducer
作用:根据action
,计算出新的state
,是一个纯函数
产生:传入state
和action
参数,返回一个新的state
const reducer = function (state,action) { // ... return new_state; }
reducer 可以进行拆分,每个子 reducer 分别负责计算 view 上面的特定组件,返回局部的 state,再通过 combineReducers 将 reducer 进行合并,就可以合并得到完整的state,刷新视图。
const chatReducer = combineReducers({ chatLog,statusMessage,userName })
redux的工作流程:
Redux应用数据的生命周期遵循下面4个步骤:
1)调用store.dispatch(action),可以在任何地方进行;
2)Redux store调用传入的reducer函数,并且将当前的state树与action传入。
3)根reducer将多个子reducer输出合并成一个单一的state树;
4)Redux store保存了根reducer返回的完整的state树。
5)新的state树就是应用的下一个状态,现在就可以根据新的state tree来渲染UI。
Redux与Flux
Flux 是一种架构思想,专门解决软件的结构问题。它跟 MVC 架构是同一类东西,但是更加简单和清晰,它跟 React 本身没什么关系,它可以用在 React 上,也可以用在别的框架上。
Flux 存在多种实现(至少15种),Facebook 官方实现版本:
View: 视图层
Action(动作):视图层发出的消息(比如mouseClick)
Dispatcher(派发器):用来接收Actions、执行回调函数
Store(数据层):用来存放应用的状态,一旦发生变动,就提醒Views要更新页面
Flux的数据管理流程:
Redux 的作用跟 Flux 是一样的,它可以看作是 Flux 的一种实现,但是又有点不同,具体的不同总结起来就是:
Redux 只有一个 store 而 Flux 里面会有多个 store 存储应用数据,并在 store 里面执行更新逻辑,当 store 变化的时候再通知 controller-view 更新自己的数据,Redux 将各个 store 整合成一个完整的 store,并且可以根据这个 store 推导出应用完整的 state。
没有 Dispatcher。 Redux 中没有 Dispatcher 的概念,它使用 reducer 来进行事件的处理,它根据应用的状态和当前的 action 推导出新的 state。Redux 中有多个 reducer,每个 reducer 负责维护应用整体 state 树中的某一部分,多个 reducer 可以通过 combineReducers 方法合成一个根reducer,这个根reducer负责维护完整的 state,当一个 action 被发出,store 会调用 dispatch 方法向某个特定的 reducer 传递该 action,reducer 收到 action 之后执行对应的更新逻辑然后返回一个新的 state,state 的更新最终会传递到根reducer处,返回一个全新的完整的 state,然后传递给 view。
简单说,Redux 和 Flux 之间最大的区别就是对 store/reducer 的抽象,Flux 中 store 是各自为战的,每个 store 只对对应的 controller-view 负责,每次更新都只通知对应的 controller-view;而 Redux 中各子 reducer 都是由根reducer统一管理的,每个子reducer的变化都要经过根reducer的整合。
flux与redux对比图:
flux
redux
React-Redux
为了方便使用,Redux 的作者封装了一个 React 专用的库 React-Redux。
这个库是可以选用的。实际项目可以选择直接使用 Redux,或者使用 React-Redux。React-Redux 虽然提供了便利,但需要掌握额外的 API,并且要遵守它的组件拆分规范。
React-Redux 将所有组件分成两大类:UI 组件和容器组件。
-
UI组件特点:
只负责 UI 的呈现,不带有任何业务逻辑
没有状态(即不使用this.state这个变量)
所有数据都由参数(this.props)提供
不使用任何 Redux 的 API
-
容器组件特点:
负责管理数据和业务逻辑,不负责 UI 的呈现
带有内部状态
使用 Redux 的 API
简单说:UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。
React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。
React-Redux 部分 API
connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])
-
connect()用于从 UI 组件生成容器组件。
connect的意思,就是将这两种组件连起来。
-
mapStateToProps是一个函数。
它的作用就是像它的名字那样,建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。
[mapStateToProps(state,[ownProps]): stateProps] (Function)
任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。该回调函数必须返回一个纯对象,这个对象会与组件的 props 合并。如果你省略了这个参数,你的组件将不会监听 Redux store。第二个参数 ownProps,为传递到组件的 props。
mapDispatchToProps是connect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。
-
<Provider> 组件
connect 方法生成容器组件以后,需要让容器组件拿到state对象,才能生成 UI 组件的参数。
React-Redux 提供Provider组件,可以让容器组件拿到state。
React-router
React-router采用react组件的方式来实现router,通过管理 URL,实现组件的切换和状态的变化。
相关路由组件:
<Router>:路由容器组件
<Route>:定义URL路径与组件的对应关系
<IndexRoute>: 指定默认情况下加载的子组件
<Link>:用于取代a元素,生成一个链接,允许用户点击后跳转到另一个路由。它基本上就是a元素的React 版本,可以接收Router的状态。
相关路由属性:
-
histroy 属性: Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。
render(( <Router >//开始创建路由表 <Route path="/" component={App}>//声明每一个路由 <Route path="/about" component={About}/> <Route path="users" component={Users}>//每个路由 </Route> </Router> ),document.getElementById('example'))