React全家桶 - umi (三)

1. umi

乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求.

2, redux解决方案--dva

• 通过把状态上提到 dva model 中,我们把数据逻辑从页面中抽离出来。
• 通过 effect 优雅地处理数据生成过程中的副作用,副作用中最常见的就是异步逻辑。
• dva model 中的数据可以注入给任意组件。
• 另外,dva 允许把数据逻辑再拆分(「页面」常常就是分隔的标志),以 namespace 区分。当你觉得有必要时,不同的 namespace 之间的 state 是可以互相访问的

如果你熟悉 React 中最基本的两个概念 props 和 state,一定知道 props 和 state 对于一个组件来讲都是数据的来源,而 state 又可以通过 props 传递给子组件,这像是一个鸡生蛋蛋生鸡的问题:到底谁是数据的源头 ?答案是 state,而且是广义的 state:它可以是 react 组件树中各级组件的 state,也可以是 react 组件树外部由其他 js 数据结构表示的 state,而 dva 管理的就是 react 组件树之外的 state: Redux。归根结底,props 是用来传导数据的,而 state 是数据改变的源泉。

3, Generator

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。从另一个角度看,也可以说 Generator 生成了一系列的值,因为可以有任意多个yield, 这也就是它的名称的来历(英语中,generator 这个词是“生成器”的意思)。

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

4, redux-saga

redux-saga 是一个用于管理应用程序 Side Effect(副作用,例如异步获取数据,访问浏览器缓存等)的 library,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。
跟redux-thunk都是解决redux异步的解决方案,但是redux-saga比较强大,可以处理比较复杂的业务场景(多个异步相互调用).redux-thunk有点破坏redux原则,redux dispatch的是一个对象,redux-thunk有可能 dispatch的是个函数. redux-saga更加遵循redux原则,dispatch的是一个比较纯粹的action对象,其次基于generator,控制力更强,能处理比较复杂的业务场景


redux-middlewares原理

使用步骤

  • 第一步; 创建saga.js文件
// store/index.js  saga注册方式
import {createStore, applyMiddleware, combineReducers} from 'redux'
import logger from 'redux-logger' // 日志记录
import thunk from 'redux-thunk' // 异步处理方案
import {counterReducer} from './count.redux'
import creatSagaMiddleware from 'redux-saga' // 创建中间件
import mySaga from './saga'
// combineReducers 将多个reducer变成一个
// 1, 创建saga中间件并注册
const sagaMiddleware = creatSagaMiddleware() 
const store = createStore(
    combineReducers({'counter': counterReducer})
    , applyMiddleware(logger, thunk, creatSagaMiddleware))
// const store = createStore(counterReducer, applyMiddleware(logger, thunk))
// 2, 中间件运行saga
sagaMiddleware.run(mySaga)
export default store
// store/saga.js
import {call, put, takeEvery} from 'redux-saga/effects'
// takeEvery 全局监听器
const userService = {
    login(uname) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (uname === 'Jerry') {
                    resolve({id: 1, name: 'Jerry', age; 20})
                } else {
                    reject('用户名或密码错误')
                }
            }, 1000)
        })
    }
}

function* login(action) {
    try {
        yield put({type: 'requestLogin'})
        const result = yield call(userService.login, action.uname)
        yield put({type: 'loginSuccess', result})
    } catch (message) {
        yield put({type: 'loginFailure', message})
    }
}

function* mySaga() {
    yield takeEvery('login', login)
}

export default mySaga
// store/user.redux.js  reducer操作
const init = {
    isLogin: false,
    loading: false,
    error: ''
}
export const user = (state = init, action) => {
    switch (action.type) {
        case 'requestLogin':
            return {
                isLogin: false,
                loading: true,
                error: ''
            };
        case 'loginSuccess':
            return {
                isLogin: true,
                loading: false,
                error: ''
            };
        case 'loginFailure':
            return {
                isLogin: true,
                loading: false,
                error: action.message
            };
        default:
            return state
    }
}

// action creator
export function login(uname) {
   return {type: 'login', uname}
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容