-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pull bare basics over from CSS-Tricks article repo
- Loading branch information
1 parent
09fa52e
commit c38ec57
Showing
4 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"parser": "babel-eslint", | ||
"env": { | ||
"browser": true, | ||
"es6": true | ||
}, | ||
"rules": { | ||
"no-const-assign": "warn", | ||
"no-this-before-super": "warn", | ||
"no-unreachable": "warn", | ||
"no-unused-vars": "warn", | ||
"constructor-super": "warn", | ||
"valid-typeof": "warn", | ||
"quotes": [2, "single", { "allowTemplateLiterals": true }] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules | ||
.DS_Store | ||
*.log | ||
npm-debug.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
export default class PubSub { | ||
constructor() { | ||
this.events = {}; | ||
} | ||
|
||
/** | ||
* Either create a new event instance for passed `event` name | ||
* or push a new callback into the existing collection | ||
* | ||
* @param {string} event | ||
* @param {function} callback | ||
* @returns {number} A count of callbacks for this event | ||
* @memberof PubSub | ||
*/ | ||
subscribe(event, callback) { | ||
|
||
let self = this; | ||
|
||
// If there's not already an event with this name set in our collection | ||
// go ahead and create a new one and set it with an empty array, so we don't | ||
// have to type check it later down-the-line | ||
if(!self.events.hasOwnProperty(event)) { | ||
self.events[event] = []; | ||
} | ||
|
||
// We know we've got an array for this event, so push our callback in there with no fuss | ||
return self.events[event].push(callback); | ||
} | ||
|
||
/** | ||
* If the passed event has callbacks attached to it, loop through each one | ||
* and call it | ||
* | ||
* @param {string} event | ||
* @param {object} [data={}] | ||
* @returns {array} The callbacks for this event, or an empty array if no event exits | ||
* @memberof PubSub | ||
*/ | ||
publish(event, data = {}) { | ||
let self = this; | ||
|
||
// There's no event to publish to, so bail out | ||
if(!self.events.hasOwnProperty(event)) { | ||
return []; | ||
} | ||
|
||
// Get each subscription and call its callback with the passed data | ||
return self.events[event].map(callback => callback(data)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import PubSub from '../lib/pubsub.js'; | ||
|
||
export default class Store { | ||
constructor(params) { | ||
let self = this; | ||
|
||
// Add some default objects to hold our actions, mutations and state | ||
self.actions = {}; | ||
self.mutations = {}; | ||
self.state = {}; | ||
|
||
// A status enum to set during actions and mutations | ||
self.status = 'resting'; | ||
|
||
// Attach our PubSub module as an `events` element | ||
self.events = new PubSub(); | ||
|
||
// Look in the passed params object for actions and mutations | ||
// that might have been passed in | ||
if(params.hasOwnProperty('actions')) { | ||
self.actions = params.actions; | ||
} | ||
|
||
if(params.hasOwnProperty('mutations')) { | ||
self.mutations = params.mutations; | ||
} | ||
|
||
// Set our state to be a Proxy. We are setting the default state by | ||
// checking the params and defaulting to an empty object if no default | ||
// state is passed in | ||
self.state = new Proxy((params.state || {}), { | ||
set: function(state, key, value) { | ||
|
||
// Set the value as we would normally | ||
state[key] = value; | ||
|
||
// Trace out to the console. This will be grouped by the related action | ||
console.log(`stateChange: ${key}: ${value}`); | ||
|
||
// Publish the change event for the components that are listening | ||
self.events.publish('stateChange', self.state); | ||
|
||
// Give the user a little telling off if they set a value directly | ||
if(self.status !== 'mutation') { | ||
console.warn(`You should use a mutation to set ${key}`); | ||
} | ||
|
||
// Reset the status ready for the next operation | ||
self.status = 'resting'; | ||
|
||
return true; | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* A dispatcher for actions that looks in the actions | ||
* collection and runs the action if it can find it | ||
* | ||
* @param {string} actionKey | ||
* @param {mixed} payload | ||
* @returns {boolean} | ||
* @memberof Store | ||
*/ | ||
dispatch(actionKey, payload) { | ||
|
||
let self = this; | ||
|
||
// Run a quick check to see if the action actually exists | ||
// before we try to run it | ||
if(typeof self.actions[actionKey] !== 'function') { | ||
console.error(`Action "${actionKey} doesn't exist.`); | ||
return false; | ||
} | ||
|
||
// Create a console group which will contain the logs from our Proxy etc | ||
console.groupCollapsed(`ACTION: ${actionKey}`); | ||
|
||
// Let anything that's watching the status know that we're dispatching an action | ||
self.status = 'action'; | ||
|
||
// Actually call the action and pass it the Store context and whatever payload was passed | ||
self.actions[actionKey](self, payload); | ||
|
||
// Close our console group to keep things nice and neat | ||
console.groupEnd(); | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Look for a mutation and modify the state object | ||
* if that mutation exists by calling it | ||
* | ||
* @param {string} mutationKey | ||
* @param {mixed} payload | ||
* @returns {boolean} | ||
* @memberof Store | ||
*/ | ||
commit(mutationKey, payload) { | ||
let self = this; | ||
|
||
// Run a quick check to see if this mutation actually exists | ||
// before trying to run it | ||
if(typeof self.mutations[mutationKey] !== 'function') { | ||
console.log(`Mutation "${mutationKey}" doesn't exist`); | ||
return false; | ||
} | ||
|
||
// Let anything that's watching the status know that we're mutating state | ||
self.status = 'mutation'; | ||
|
||
// Get a new version of the state by running the mutation and storing the result of it | ||
let newState = self.mutations[mutationKey](self.state, payload); | ||
|
||
// Merge the old and new together to create a new state and set it | ||
self.state = Object.assign(self.state, newState); | ||
|
||
return true; | ||
} | ||
} |