References:
结合官方文档:
此处不再赘述dva项目初始化的5个api(const myapp=dva()/plugins(dva-loading)/model(require)/router/start)
- 简述dva框架快速上手建立一个简单页面:
- 编写UI组件:components/ProductList.js
- 定义路由routes/Products.js,添加路由信息到路由表routes/router.js
- 定义model:models/products.js处理数据和逻辑
- connect UI组件和容器组件:重新编辑routes/Products.js,包括使用connect 定义异步方法dispatch action
有关于dva框架的使用:(入口文件的配置,五个关键api)
1. Initialize
const myApp = dva({
initialState: window.INITIAL_STATE,
history: createBrowserHistory(),
onAction: middleware, // 注册 redux 中间件
onError(e) {
console.log(e.message);
},
});
2. Plugins 配置插件或则dva hooks(dva提供了丰富的插件的一种处理loading状态)
myApp.use(createLoading());
dva-loading的使用 :dva-loading 实践用法
3. Model 注册model:Model 数据逻辑处理,数据流动的地方。
app.model(require('./models/example').default);
关于多个models的使用:
models文件夹下新建index.js:
const context = require.context('./', false, /\.js$/); //这里的false表示不遍历子目录
export default context
.keys() //object.keys()返回所有可枚举属性
.filter(item => item !== './index.js') //过滤掉当前的index.js
.map(key => context(key)); //获取所有的key值包含到context中
入口文件中:
import models from './models/index'
[...models].forEach(model => app.model(model.default||model))// 用的箭头函数哦
ok了。其他参考:webpack中require.context的作用(简化import)
4. Router
app.router(require('./router').default);
5. Start
app.start('#root');
curd_demo的建立全流程:
简介:CURD操作
CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。它代表
创建(Create) 、 更新(Update) 、 读取(Read) 和 删除(Delete) 操作。CURD 定义了用于处
理数据的基本原子操作。
1.整理需求
2.确认前后端交互
3.添加model:
5个属性:
namespace:命名空间(重要)
model
的命名空间,同时也是他在全局 state
上的属性,只能用字符串,我们发送在发送 action
到相应的 reducer
时,就会需要用到namespace
。
同时用effect副作用获取state值的时候也会用到命名空间:(todo就是命名空间)
const tempList=yield select(state=>state.todo.list);
state:初始值
优先级比在dva中初始化时的优先级低,但是项目中基本上初始的state值均在这里定义。
reducers:对象(用于处理同步操作。等同于 redux 里的 reducer,唯一可以修改 state 的地方,
由 action 触发。)
setItemList(state, { payload = {} }) {
const {
items, pageNum, totalCount, id,
} = payload;
return {
...state,
itemList: items,
id,
pagination: {
current: pageNum,
total: totalCount,
},
};
},
effects:对象(用于处理异步操作和业务逻辑。不直接修改 state。由 action 触发,可以触发 action,
可以和服务器交互,可以获取全局 state 的数据。)
*fetchItemList({ payload = {} }, { call, put }) {
//下面的fetchItemList方法是异步调数据的方法
//call:执行异步函数
//put:发出一个 Action,类似于 dispatch
const { data = {} } = yield call(fetchItemList, { body: payload });
yield put({ type: 'setItemList', payload: data || {} });
},
dva框架中的effects 模块的设计思想来源于 redux-saga
框架:
redux-saga时管理redux应用异步操作的中间件,通过创建sagas将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。
下面只介绍几个常用的redux-saga中创建effect的函数:
- select(selector, ...args):指示 middleware调用提供的选择器获取Store上的state数据,你也可以简单的把它理解为redux框架中获取store上的 state数据一样的功能 :
store.getState()
const tempList=yield select(state=>state.todo.list);
- call(fn, ...args):就是可以调用其他函数的函数,它命令 middleware 来调用fn 函数, args为函数的参数,注意: fn 函数可以是一个 Generator 函数,也可以是一个返回 Promise 的普通函数,call 函数也是阻塞 effect。(一般在这里调后端数据)
const {data={}}=yield call(todoService.query,value);
- put(action):用来发送action的 effect,你可以简单的把它理解成为redux框架中的dispatch函数,当put一个action后,reducer中就会计算新的state并返回,注意: put 也是阻塞 effect
-
yield put({type:'save',payload:{list}})
subscriptions:用于订阅一个数据源,然后根据需要 dispatch 相应的 action,数据源可以是当前的时间、location 变化、history 路由变化等。
4.添加组件:(UI组件)
通过props承接并且展示数据
5.添加路由:把组件挂载到路由上,这样我们在访问路由时,组件才会渲染到页面上。
配置路由表固定方式-->react-router-config使用:React Router Config(能让你像使用vue-router一样使用react-router)
6.关联组件:UI组件和容器组件,把UI组件生成容器组件(React-Redux 规定,所有的 UI (dumb)组件都由用户提供,容器组件(smart)则是由 React-Redux 自动生成。也就是说,
用户负责视觉层,状态管理则是全部交给它。)
7.请求服务端数据:componentDidMount中请求服务端数据
完整的过程是这样的:通过在组件中 dispatch action 触发 effect,
在 effect 中调用 service 中的方法请求接口,拿到响应数据后再触发 action,
reducer 完成对 state 的修改。因为在 Step6 中,我们关联了组件和 Model,(mapStateToProps)
因此当 state 变化是,新的 state 会作为组件的 props 传递给组件,从而重新渲染。
补:dva+react-router-config简单demo:(已经实现计数器以及todolist功能)
https://github.com/LynnWonder/dva-react-counter.git
react-router-config使用:
dva项目入口文件中初始化时引入app.router(require('./routes/index'));
routes/index.js配置路由,根组件放入一个空的组件<----传入routes路由表(routes/config.js)
routes/config.js类似于vue-router一样配置路由表,可以嵌套,可以引入react-router的Redirect重定向
父组件中渲染路由:(是config.js里面定义的父组件,注意和我说的空根组件区分,不然页面出现两个父组件哦~)
{renderRoutes(this.props.route.routes)}