浅谈redux以及react

写在前头

redux 简介

随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。

如果这还不够糟糕,考虑一些来自前端开发领域的新需求,如更新调优、服务端渲染、路由跳转前请求数据等等。前端开发者正在经受前所未有的复杂性,难道就这么放弃了吗?当然不是。

这里的复杂性很大程度上来自于:我们总是将两个难以理清的概念混淆在一起:变化和异步。 如果把二者分开,能做的很好,但混到一起,就变得一团糟。一些库如 React 试图在视图层禁止异步和直接操作 DOM 来解决这个问题。美中不足的是,React 依旧把处理 state 中数据的问题留给了我们自己。而 redux 就可以来帮我管理这些状态;

demo 演示

浅谈redux以及react

demo 结构树

├── config-overrides.js ├── .gitignore ├── package.json ├── package-lock.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json ├── README.md └── src ├── App.js ├── Demo │ ├── actionCreate.js │ ├── Demo.jsx │ ├── react-redux.js │ ├── reducer.js │ ├── redux.js │ ├── style.css │ └── thunk.js └── index.js

一、 redux API createStore 的实现

首先我们先结合 reducer 以及 action 的知识简单实现开头展示的 demo, 并逐步揭晓 createStore 的神秘面纱;

1.1 准备工作:

创建 reducer 并导出 reducer

// reducer.js const initState = { user: 'qianyin', age: 18, sex: '男' }; export const reducer = (state=initState, action) => { switch(action.type){ case 'USER_UPDATE': return {...state, ...action.payload}; case 'AGE_GROW': return {...state, age: state.age + 1}; case 'SEX_UPDATE': return {...state, ...action.payload}; default: return state; } }

创建 action 创建函数

// actionCreate.js export const changeUser = (user) => { return { payload:{user}, type: 'USER_UPDATE', }; } export const changeAge = () => { return { type: 'AGE_GROW' }; }

通过 react 在页面上预先绘制出基本的元素

/* style.css */ .btn{ height: 31px; } .input{ height: 25px; }

// Demo.jsx import React from 'react'; import './style.css'; export default class Demo extends React.Component{ onChange = () => {} onClick = () => {} render(){ return ( <div> <p>user: xxx, age: xxx</p> user: <input type="text" className="input" onChange={this.onChange}/> &nbsp; <button className="btn" onClick={this.onClick}>年龄增长</button> </div> ); } }

最终页面将渲染如下:

浅谈redux以及react

1.2 demo 的初次实现代码

创建全局状态 state;

创建监听队列;

针对监听队列,新增函数用于将指定监听对象添加到队列中;

在函数 dispatch 中执行 reducer 将返回值作为新的 state, 同时依次执行监听对象;

默认执行一次 dispatch 给定一个 type 相对唯一的 action, 目的是为了匹配 reducer 的默认状态值,从而实现对 redux state 的初始化;

在组件 Demo 通过在函数 update 使用 this.setState 将全局 state 保存到 react state 中,并将函数 update 添加到监听队列中;从而使得当我们一旦试图通过 dispatch 修改全局状态时,能够及时更新 react state 最终触发 react 生命周期 render;

在 react 生命周期 componentDidMount 中我们除了将 update 添加到监听队列以外,还需手动执行一次 update 其主要目的就是为了首次初始化 react state;

// Demo.jsx import React from 'react'; import { changeAge, changeUser } from './actionCreate'; import { reducer } from './reducer'; import './style.css'; let state; const listeners = []; const subscribe = (listener) => { listeners.push(listener); } const dispatch = (action) => { state = reducer(state, action); console.log(state); listeners.forEach(v => v()); } dispatch({type: '%$&HJKAJJHDJHJ'}); export default class Demo extends React.Component{ state = {user: 'xxx', age: 'xxx'}; componentDidMount(){ subscribe(this.update); this.update(); } update = () => { this.setState(state); } onChange = (e) => { dispatch(changeUser(e.target.value)); } onClick = () => { dispatch(changeAge()); } render(){ return ( <div> <p>user: {this.state.user}, age: {this.state.age}</p> user: <input type="text" className="input" onChange={this.onChange}/> &nbsp; <button className="btn" onClick={this.onClick}>年龄增长</button> </div> ); } }

1.3 API createStore 的实现

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/409a9e00d2956978089f2b630a280285.html