自己实现Redux
不使用react,直接使用原生的html/js来写一个简易的的redux
基本的状态管理及数据渲染
<!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 principle 01</title>
</head>
<body>
<h1>redux principle</h1>
<div class="counter">
<span class="btn" onclick="dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
<span class="count" id="count"></span>
<span class="btn" id="add" onclick="dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
</div>
<script>
// 定义一个计数器的状态
const countState = {
count: 10
}
// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
const changeState = (action) => {
switch(action.type) {
// 处理减
case 'COUNT_DECREMENT':
countState.count -= action.number
break;
// 处理加
case 'COUNT_INCREMENT':
countState.count += action.number
break;
default:
break;
}
}
// 定义一个方法用于渲染计数器的dom
const renderCount = (state) => {
const countDom = document.querySelector('#count')
countDom.innerHTML = state.count
}
// 首次渲染数据
renderCount(countState)
// 定义一个dispatch的方法,接收到动作之后,自动调用
const dispatch = (action) => {
changeState(action)
renderCount(countState)
}
</script>
</body>
</html>
创建createStore方法
<!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 principle 02</title>
</head>
<body>
<h1>redux principle</h1>
<div class="counter">
<span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
<span class="count" id="count"></span>
<span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
</div>
<script>
// 定义一个方法,用于集中管理state和dispatch
const createStore = (state, changeState) => {
// getState用于获取状态
const getState = () => state
// 定义一个监听器,用于管理一些方法
const listeners = []
const subscribe = (listener) => listeners.push(listener)
// 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果
const dispatch = (action) => {
// 调用changeState来处理数据
changeState(state, action)
// 让监听器里的所以方法运行
listeners.forEach(listener => listener())
}
return {
getState,
dispatch,
subscribe
}
}
// 定义一个计数器的状态
const countState = {
count: 10
}
// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
const changeState = (state, action) => {
switch(action.type) {
// 处理减
case 'COUNT_DECREMENT':
state.count -= action.number
break;
// 处理加
case 'COUNT_INCREMENT':
state.count += action.number
break;
default:
break;
}
}
// 创建一个store
const store = createStore(countState, changeState)
// 定义一个方法用于渲染计数器的dom
const renderCount = () => {
const countDom = document.querySelector('#count')
countDom.innerHTML = store.getState().count
}
// 初次渲染数据
renderCount()
// 监听,只要有dispatch,这个方法就会自动运行
store.subscribe(renderCount)
</script>
</body>
</html>
让changeState方法变为一个纯函数
<!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 principle 03</title>
</head>
<body>
<h1>redux principle</h1>
<div class="counter">
<span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
<span class="count" id="count"></span>
<span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
</div>
<script>
// 定义一个方法,用于集中管理state和dispatch
const createStore = (state, changeState) => {
// getState用于获取状态
const getState = () => state
// 定义一个监听器,用于管理一些方法
const listeners = []
const subscribe = (listener) => listeners.push(listener)
// 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果
const dispatch = (action) => {
// 调用changeState来处理数据
state = changeState(state, action)
// 让监听器里的所有方法运行
listeners.forEach(listener => listener())
}
return {
getState,
dispatch,
subscribe
}
}
// 定义一个计数器的状态
const countState = {
count: 10
}
// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
const changeState = (state, action) => {
switch(action.type) {
// 处理减
case 'COUNT_DECREMENT':
return {
...state,
count: state.count - action.number
}
// 处理加
case 'COUNT_INCREMENT':
return {
...state,
count: state.count + action.number
}
default:
return state
}
}
// 创建一个store
const store = createStore(countState, changeState)
// 定义一个方法用于渲染计数器的dom
const renderCount = () => {
const countDom = document.querySelector('#count')
countDom.innerHTML = store.getState().count
}
// 初次渲染数据
renderCount()
// 监听,只要有dispatch,这个方法就会自动运行
store.subscribe(renderCount)
</script>
</body>
</html>
合并state和changeState(最终版)
<!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 principle 04</title>
</head>
<body>
<h1>redux principle</h1>
<div class="counter">
<span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
<span class="count" id="count"></span>
<span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
</div>
<script>
// 定义一个方法,用于集中管理state和dispatch, changeState改名了,专业的叫法是reducer
const createStore = (reducer) => {
// 定义一个初始的state
let state = null
// getState用于获取状态
const getState = () => state
// 定义一个监听器,用于管理一些方法
const listeners = []
const subscribe = (listener) => listeners.push(listener)
// 定义一个dispatch方法,让每次有action传入的时候返回reducer执行之后的结果
const dispatch = (action) => {
// 调用reducer来处理数据
state = reducer(state, action)
// 让监听器里的所有方法运行
listeners.forEach(listener => listener())
}
// 初始化state
dispatch({})
return {
getState,
dispatch,
subscribe
}
}
// 定义一个计数器的状态
const countState = {
count: 10
}
// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
const changeState = (state, action) => {
// 如果state是null, 就返回countState
if (!state) return countState
switch(action.type) {
// 处理减
case 'COUNT_DECREMENT':
return {
...state,
count: state.count - action.number
}
// 处理加
case 'COUNT_INCREMENT':
return {
...state,
count: state.count + action.number
}
default:
return state
}
}
// 创建一个store
const store = createStore(changeState)
// 定义一个方法用于渲染计数器的dom
const renderCount = () => {
const countDom = document.querySelector('#count')
countDom.innerHTML = store.getState().count
}
// 初次渲染数据
renderCount()
// 监听,只要有dispatch,renderCount就会自动运行
store.subscribe(renderCount)
</script>
</body>
</html>