redux是一个将ui与数据操作分离的框架,可以与vue或者react配合使用。保证了数据集中修改,然后渲染,可以防止用户在外部随意修改state状态树。redux利用store来统一管理state,当ui响应用户操作事件会触发dispatch操作,dispatch类似一个通知,他不会直接修改state,而是将要做什么事情action以通知的形式发送给store。store根据action的类型type来判断执行什么操作来改变state。当state改变之后,调用渲染方法,改变ui。
我们可以使用redux框架来做一个简单的示例:这也是github上原生计数器redux示例,不用结合react,直接在html页面中引入redux.min.js库文件,然后编码。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>redux</title>
<script type="text/javascript" src="node_modules/redux/dist/redux.min.js"></script>
</head>
<body>
<div>
<div id="value" style="height: 30px;"></div>
<div style="padding:5px 0">
<button id="increment">increment</button>
</div>
<div style="padding:5px 0">
<button id="decrement">decrement</button>
</div>
<div style="padding:5px 0">
<button id="incrementIfOdd">incrementIfOdd</button>
</div>
<div style="padding:5px 0">
<button id="incrementAsync">incrementAsync</button>
</div>
</div>
<script type="text/javascript">
$ = (id) => document.getElementById(id)
function reducer(state,action){
if(state==undefined){
return 0
}
switch(action.type){
case 'increment':
return state + 1
case 'decrement':
return state - 1
default:
return state
}
}
var store = Redux.createStore(reducer)
function render(){
$('value').innerHTML = store.getState().toString()
}
$('increment').addEventListener('click',(e)=>{
store.dispatch({type:'increment'})
})
$('decrement').addEventListener('click',(e)=>{
store.dispatch({type:'decrement'})
})
$('incrementIfOdd').addEventListener('click',(e)=>{
if(store.getState()%2!==0){
store.dispatch({type:'increment'})
}
})
$('incrementAsync').addEventListener('click',(e)=>{
setTimeout(()=>store.dispatch({type:'increment'}),1000)
})
render()
store.subscribe(render)
</script>
</body>
</html>
在浏览器中打开页面:
例子很简单,我们点击increment按钮,计数器自动+1,当我们点击decrement按钮,计数器-1,点击incrementIfOdd按钮时,如果计数器是奇数就+1,点击incrementAsync按钮时,计数器延时一秒+1。
上面的例子如果用原生的javascript也很容易实现,就是设置一个变量counter,当我们点击各自按钮,然后就可以根据对应的逻辑设置counter +1还是-1,最后再将counter的值写到页面的id=value元素中。
使用redux,可以将点击操作指令化,就是只是发送一个指令action,告诉store要干什么,具体怎么操作,就由store去告诉reducer,reducer会根据先前的状态state,结合action.type计算出新的state然后返回,store因为订阅了页面渲染方法render,所以会在state发生改变之后,重新渲染页面,将新的state绘制到页面中。
redux的思想就是将用户响应集中处理,而不是随意在任何地方就可以处理,这样状态是不可预测的,有了redux,页面上的状态变成可预测的。
这里有几个概念,dispatch:指令分发,subscribe:订阅事件,reducer:可以理解为store核心处理逻辑。createStore:创建存储中心store。所有的状态state均在store这里维护和提供对外访问的机制getState(),我们在渲染的时候就是通过store.getState()来获取状态值,最后绘制在页面的。