-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstore.js
121 lines (96 loc) · 3.06 KB
/
store.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
window.storeImmutable = (() => {
'use strict'
// shallow equal
const shallowEqual = (item1, item2) => {
if(item1 === item2) return true
if(typeof item1 === typeof item2 && typeof item1 === "object") {
let item1Keys = Object.keys(item1)
let item2Keys = Object.keys(item2)
if(item1Keys.length !== item2Keys.length) return false
if(Array.isArray(item1) !== Array.isArray(item2)) return false
let anyValueDifference = false
for(var key in item1) {
if(!item1.hasOwnProperty(key)) continue
if(item1[key] !== item2[key]) {
anyValueDifference = true
break
}
}
if(!anyValueDifference) return true
}
return false
}
// store instance builder
function createStore(initState = {}) {
let state = initState
let history = [ initState ]
let historyPointer = 0
let listeners = []
// on change
const onChange = () => {
listeners.forEach(callback => callback(state))
}
const changeHistoryPointer = (newPointIndex) => {
if(newPointIndex < 0 || newPointIndex > history.length - 1) {
return
}
state = history[newPointIndex]
historyPointer = newPointIndex
onChange()
}
const recordHistory = (newState) => {
// if history is detached, so remove all
// histories next to current detached one
if(historyPointer !== history.length - 1) {
history = history.filter((h, index) => index <= historyPointer)
}
history.push(newState)
historyPointer ++
}
const API = {
getState: () => state,
setState: (callback) => {
let newState = callback(state)
if(shallowEqual(newState, state)) {
console.log("nothing has changed (shallow comparision)")
return
}
recordHistory(newState)
state = newState
onChange()
},
nextState: () => changeHistoryPointer(historyPointer + 1),
prevState: () => changeHistoryPointer(historyPointer - 1),
getHistoryCount: () => history.length,
getCurrentHistoryNum: () => historyPointer + 1,
subscribe: (listener) => {
let alreadyExists = listeners.find(item => item === listener)
if(alreadyExists) {
console.log("listener already exists")
return
}
else {
listeners.push(listener)
}
},
unsubscribe: (listener) => {
let existsIndex = listeners.findIndex(item => item === listener)
if(existsIndex < 0) {
console.log("listener not found")
return
}
else {
listeners = [
...listeners.slice(0, existsIndex),
...listeners.slice(existsIndex + 1),
]
}
}
}
return API
}
return {
createStore,
shallowEqual,
}
})()