必要
購読、購読解除。
更新要求を発行します。
実装プロセス
1.まず、createStoreは、Storeオブジェクトの合計を返す関数です。
サブスクライブメソッド、送信リクエストメソッド、ステータス取得の3つの機能があります。
export default function (reducer, initState) {
function subscribe(fn) {
}
function dispatch(action) {
}
function getState() {
}
return {
subscribe,
dispatch,
getState
}
}
2.前処理。
パラメータ、さまざまな初期化を保存します。
//副本
let cReducer = reducer
let cState = initState
//订阅列表
let cListeners
let nListeners = cListeners = []
//状态标记
let isDispatching = false
let isSubscribed = false
//照搬
function ensureCanMutateNextListeners() {
if (nListeners === cListeners) {
nListeners = cListeners.slice()
}
}
3.サブスクリプションを実装します
//订阅
function subscribe(fn) {
if (isDispatching) {
return
}
isSubscribed = true
ensureCanMutateNextListeners()
nListeners.push(fn)
//取消
return function () {
if (isDispatching) {
return
}
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nListeners.indexOf(fn)
nListeners.splice(index, 1)
}
}
4.アップデートを実現します
function dispatch(action) {
if (isDispatching) {
return
}
if (typeof action === "object") {
try {
isDispatching = true
cState = cReducer(cState, action)
} finally {
isDispatching = false
}
const listeners = cListeners = nListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
} else if (typeof action === "function") {
action(dispatch)
}
}
5.ステータスを取得します
function getState() {
return cState;
}
すべてのコード
export default function (reducer, initState) {
//副本
let cReducer = reducer
let cState = initState
//订阅列表
let cListeners
let nListeners = cListeners = []
//状态标记
let isDispatching = false
let isSubscribed = false
//照搬
function ensureCanMutateNextListeners() {
if (nListeners === cListeners) {
nListeners = cListeners.slice()
}
}
//订阅
function subscribe(fn) {
if (isDispatching) {
return
}
isSubscribed = true
ensureCanMutateNextListeners()
nListeners.push(fn)
//取消
return function () {
if (isDispatching) {
return
}
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nListeners.indexOf(fn)
nListeners.splice(index, 1)
}
}
function dispatch(action) {
if (isDispatching) {
return
}
if (typeof action === "object") {
try {
isDispatching = true
cState = cReducer(cState, action)
} finally {
isDispatching = false
}
const listeners = cListeners = nListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
} else if (typeof action === "function") {
action(dispatch)
}
}
function getState() {
return cState;
}
return {
subscribe,
dispatch,
getState
}
}
テスト:カウンター
レデューサー
import createStore from "../../react-state";
let initState = {
count: 0
};
function CounterReducer(state, action) {
const {
type, amount} = action;
switch (type) {
case "Normal":
if (state.count + amount >= 0) {
return {
count: state.count + amount};
} else {
return state;
}
default:
return state;
}
}
export default createStore(CounterReducer, initState);
アクション
export const Normal = v => ({
type: "Normal", amount: v
})
export const Async = (v, time) => {
return (dispatch) => {
setTimeout(() => {
dispatch(Normal(v));
}, time);
}
}
カウンター
import {
Component} from "react";
import store from "./Reducer";
import {
Normal, Async} from "./Action";
export default class Counter extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.setState({
})
})
}
render() {
return <h1>{
store.getState().count}
<button onClick={
() => store.dispatch(Normal(1))}>同步加</button>
<button onClick={
() => store.dispatch(Normal(-1))}>同步减</button>
<button onClick={
() => store.dispatch(Async(1, 1000))}>异步加</button>
<button onClick={
() => store.dispatch(Async(-1, 1000))}>异步减</button>
<button onClick={
() => this.unsubscribe()}>取消订阅</button>
</h1>
}
}
効果:
簡素化する
フロントエンドJSはシングルスレッドモデルであるため、多くのことを省略できます。
export default function (reducer, initState) {
//副本
let cReducer = reducer
let cState = initState
//订阅列表
let cListeners = []
//订阅
function subscribe(fn) {
cListeners.push(fn)
//取消
return function () {
cListeners.splice(cListeners.indexOf(fn), 1)
}
}
function dispatch(action) {
if (typeof action === "object") {
cState = cReducer(cState, action)
for (let i = 0; i < cListeners.length; i++) {
cListeners[i]()
}
} else if (typeof action === "function") {
action(dispatch)
}
}
function getState() {
return cState;
}
return {
subscribe,
dispatch,
getState
}
}