随着 javascript 单页应用的不断发展,javascript 需要管理比以往都要多的状态,管理不断变化的 state 非常困难,数据流动不断变的模糊不可预测,代码的开发与维护成为了变得越来越困难.redux 这类状态管理框架变出现了,通过限制更新发生的时间和方式,来使 state 的变化变得可以预测.
redux 是一个很有用的框架,但是并不是非用不可,而是当你自己觉得可能需要 redux 的时候,就会找到他,并且使用他(还有其他同类框架)
当你有大量的,随时间变化的数据
当你需要一个单一可靠的 state 数据源
当你把所有 state 放到顶部,或者父子兄弟之间的数据通信让你焦头烂额的时候
三大原则单一数据源 (整个应用的 state 存放在一个 object tree 中,这个 object tree 只存在与唯一的一个 store 中)
state 是只读的,唯一能够改变 state 的只有 action
只能通过纯函数进行修改
state 基本概念state 是数据的状态集合,一般为一个对象
let state = { singer: [ { name: "刘德华", desc: "一位演员" } ], actor: [ { name: "郭富城", desc: "一位歌手" } ] }; action 基本概念action 是一个普通的 javacript 对象,用来更新 state 并同时描述发生了什么.可以知道应用到底发生了什么,变化后可以知道为什么改变.
let action = { type: "ADD_SINGER", payload: { name: "黎明", desc: "一位很好的歌手" } }; let action2 = { type: "ADD_ACTOR", payload: { name: "周润发", desc: "一位很好的演员" } }; action 生成器(action 是一个对象,action 生成器是一个函数,两个不同的概念)
用于 action 的复用,实际上是返回一个对象的函数
function addSinger_action(payload) { return { type: "ADD_SINGER", payload }; } function addActor_action(payload) { return { type: "ADD_ACTOR", payload }; } reducer 基本概念reducer 是一个为了把 state 和 action 连接起来而诞生的纯函数,接收 state 和 action,然后返回一个新的 state
function add_singer(state, action) { if (action.type === "ADD_SINGER") { console.warn("发起了action=ADD_SINGER"); state = Object.assign({}, state, { singer: state.singer.concat([action.payload]) }); return state; } return state; } function add_actor(state, action) { if (action.type === "ADD_ACTOR") { console.warn("发起了action=>ADD_ACTOR"); state = Object.assign({}, state, { actor: state.actor.concat([action.payload]) }); return state; } return state; }改变 state
state = add_actor( state, addActor_action({ name: "周润发", desc: "一位很好的演员" }) ); console.log(state); state = add_singer( state, addSinger_action({ name: "黎明", desc: "一位很好的歌手" }) ); console.log(state);上面就是 state,action 以及 reducer 连接二者的方式,redux 里面提供了更多的便捷操作
redux 基础
redux 中的 action
action 主要是把数据从应用传到 store 的有效载荷,它是 store 的唯一来源,通过 reducer 定义的 state 是初始化,一般写法中多设置为 null,undefined,{},[]等.通过 store.dispatch()将 action 传到 store.为了使用方便,一般会用 action 生成器来生成 action.
redux 只用把 action 生成器的结果传给 dispatch()就可以发起 dispatch
import { createStore } from "../redux/index"; import reducer from './reducer'; const ADD_SINGER = "ADD_SINGER"; const ADD_ACTOR = "ADD_ACTOR"; const store = createStore(reducer); store.dispatch( addSinger_action({ name: "周华健", desc: "一位大帅哥" }) ); store.dispatch( addActor_action({ name: "谢安琪", desc: "一位小美女" }) ); console.log(store.getState()); function addSinger_action(payload) { return { type: ADD_SINGER, payload }; } function addActor_action(payload) { return { type: ADD_ACTOR, payload }; } 我们也可以创建一个函数用于返回 dispatch 触发器 bound_add_singer_action({ name: "周华健", desc: "一位大帅哥" }); bound_add_actor_action({ name: "谢安琪", desc: "位小美女" }); function bound_add_singer_action(payload) { return store.dispatch(addSinger_action(payload)); } function bound_add_actor_action(payload) { return store.dispatch(addActor_action(payload)); } console.log(store.getState());action 主要包含 action 对象,action_creater()生成器,bound_action_creater()绑定函数
//我是action {type:"我是type",payload:"我是数据"} //我是action生成器,我是来返回action对象 function action_creater(){ return {type:"我是type",payload:"我是数据"} } //我是bound_action_creater绑定函数,我是获取action生成器的返回值去触发dispatch() function bound_action_creater(){ store.dispatch(action_creater()); }redux 中 reducer
(oldState,action)=> newState 这种就是一个最简单的 reducer.
禁止事项
修改传入的参数
执行有副作用的操作,如 api 请求,变量修改,路由跳转