mirror of https://github.com/sveltejs/svelte
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
1.9 KiB
87 lines
1.9 KiB
import {
|
|
assign,
|
|
blankObject,
|
|
differs,
|
|
dispatchObservers,
|
|
get,
|
|
observe
|
|
} from './shared.js';
|
|
|
|
function Store(state) {
|
|
this._state = state ? assign({}, state) : {};
|
|
this._observers = { pre: blankObject(), post: blankObject() };
|
|
this._changeHandlers = [];
|
|
this._dependents = [];
|
|
}
|
|
|
|
assign(Store.prototype, {
|
|
get,
|
|
observe
|
|
}, {
|
|
_add: function(component, props) {
|
|
this._dependents.push({
|
|
component: component,
|
|
props: props
|
|
});
|
|
},
|
|
|
|
_remove: function(component) {
|
|
let i = this._dependents.length;
|
|
while (i--) {
|
|
if (this._dependents[i].component === component) {
|
|
this._dependents.splice(i, 1);
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
|
|
onchange: function(callback) {
|
|
this._changeHandlers.push(callback);
|
|
return {
|
|
cancel: function() {
|
|
var index = this._changeHandlers.indexOf(callback);
|
|
if (~index) this._changeHandlers.splice(index, 1);
|
|
}
|
|
};
|
|
},
|
|
|
|
set: function(newState) {
|
|
var oldState = this._state,
|
|
changed = {},
|
|
dirty = false;
|
|
|
|
for (var key in newState) {
|
|
if (differs(newState[key], oldState[key])) changed[key] = dirty = true;
|
|
}
|
|
if (!dirty) return;
|
|
|
|
this._state = assign({}, oldState, newState);
|
|
|
|
for (var i = 0; i < this._changeHandlers.length; i += 1) {
|
|
this._changeHandlers[i](this._state, changed);
|
|
}
|
|
|
|
dispatchObservers(this, this._observers.pre, changed, this._state, oldState);
|
|
|
|
var dependents = this._dependents.slice(); // guard against mutations
|
|
for (var i = 0; i < dependents.length; i += 1) {
|
|
var dependent = dependents[i];
|
|
var componentState = {};
|
|
dirty = false;
|
|
|
|
for (var j = 0; j < dependent.props.length; j += 1) {
|
|
var prop = dependent.props[j];
|
|
if (prop in changed) {
|
|
componentState['$' + prop] = this._state[prop];
|
|
dirty = true;
|
|
}
|
|
}
|
|
|
|
if (dirty) dependent.component.set(componentState);
|
|
}
|
|
|
|
dispatchObservers(this, this._observers.post, changed, this._state, oldState);
|
|
}
|
|
});
|
|
|
|
export default Store; |