mirror of https://github.com/sveltejs/svelte
parent
22775d5cd9
commit
3a5080b423
@ -1 +1,2 @@
|
|||||||
|
--bail
|
||||||
test/test.js
|
test/test.js
|
@ -1,9 +0,0 @@
|
|||||||
export default {
|
|
||||||
input: 'store.js',
|
|
||||||
output: {
|
|
||||||
file: 'store.umd.js',
|
|
||||||
format: 'umd',
|
|
||||||
name: 'svelte',
|
|
||||||
extend: true
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,29 +0,0 @@
|
|||||||
interface Options {
|
|
||||||
immutable: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Cancellable {
|
|
||||||
cancel: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Tuple<T extends any, L extends number> extends Array<T> {
|
|
||||||
0: T;
|
|
||||||
length: L;
|
|
||||||
}
|
|
||||||
|
|
||||||
type State = Record<string, any>;
|
|
||||||
|
|
||||||
export declare class Store {
|
|
||||||
constructor(state: State, options?: Options);
|
|
||||||
|
|
||||||
public compute<L extends number>(
|
|
||||||
key: string,
|
|
||||||
dependencies: Tuple<string, L>,
|
|
||||||
fn: (...dependencies: Tuple<any, L>) => any,
|
|
||||||
): void;
|
|
||||||
|
|
||||||
public fire(name: string, data?: any): void;
|
|
||||||
public get(): State;
|
|
||||||
public on(name: string, callback: (data: any) => void): Cancellable;
|
|
||||||
public set(state: State): void;
|
|
||||||
}
|
|
@ -1,174 +0,0 @@
|
|||||||
import {
|
|
||||||
assign,
|
|
||||||
blankObject,
|
|
||||||
_differs,
|
|
||||||
_differsImmutable,
|
|
||||||
get,
|
|
||||||
on,
|
|
||||||
fire
|
|
||||||
} from './shared.js';
|
|
||||||
|
|
||||||
function Store(state, options) {
|
|
||||||
this._handlers = {};
|
|
||||||
this._dependents = [];
|
|
||||||
|
|
||||||
this._computed = blankObject();
|
|
||||||
this._sortedComputedProperties = [];
|
|
||||||
|
|
||||||
this._state = assign({}, state);
|
|
||||||
this._differs = options && options.immutable ? _differsImmutable : _differs;
|
|
||||||
}
|
|
||||||
|
|
||||||
assign(Store.prototype, {
|
|
||||||
_add(component, props) {
|
|
||||||
this._dependents.push({
|
|
||||||
component: component,
|
|
||||||
props: props
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_init(props) {
|
|
||||||
const state = {};
|
|
||||||
for (let i = 0; i < props.length; i += 1) {
|
|
||||||
const prop = props[i];
|
|
||||||
state['$' + prop] = this._state[prop];
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
},
|
|
||||||
|
|
||||||
_remove(component) {
|
|
||||||
let i = this._dependents.length;
|
|
||||||
while (i--) {
|
|
||||||
if (this._dependents[i].component === component) {
|
|
||||||
this._dependents.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_set(newState, changed) {
|
|
||||||
const previous = this._state;
|
|
||||||
this._state = assign(assign({}, previous), newState);
|
|
||||||
|
|
||||||
for (let i = 0; i < this._sortedComputedProperties.length; i += 1) {
|
|
||||||
this._sortedComputedProperties[i].update(this._state, changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fire('state', {
|
|
||||||
changed,
|
|
||||||
previous,
|
|
||||||
current: this._state
|
|
||||||
});
|
|
||||||
|
|
||||||
this._dependents
|
|
||||||
.filter(dependent => {
|
|
||||||
const componentState = {};
|
|
||||||
let dirty = false;
|
|
||||||
|
|
||||||
for (let j = 0; j < dependent.props.length; j += 1) {
|
|
||||||
const prop = dependent.props[j];
|
|
||||||
if (prop in changed) {
|
|
||||||
componentState['$' + prop] = this._state[prop];
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirty) {
|
|
||||||
dependent.component._stage(componentState);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.forEach(dependent => {
|
|
||||||
dependent.component.set({});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.fire('update', {
|
|
||||||
changed,
|
|
||||||
previous,
|
|
||||||
current: this._state
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_sortComputedProperties() {
|
|
||||||
const computed = this._computed;
|
|
||||||
const sorted = this._sortedComputedProperties = [];
|
|
||||||
const visited = blankObject();
|
|
||||||
let currentKey;
|
|
||||||
|
|
||||||
function visit(key) {
|
|
||||||
const c = computed[key];
|
|
||||||
|
|
||||||
if (c) {
|
|
||||||
c.deps.forEach(dep => {
|
|
||||||
if (dep === currentKey) {
|
|
||||||
throw new Error(`Cyclical dependency detected between ${dep} <-> ${key}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
visit(dep);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!visited[key]) {
|
|
||||||
visited[key] = true;
|
|
||||||
sorted.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key in this._computed) {
|
|
||||||
visit(currentKey = key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
compute(key, deps, fn) {
|
|
||||||
let value;
|
|
||||||
|
|
||||||
const c = {
|
|
||||||
deps,
|
|
||||||
update: (state, changed, dirty) => {
|
|
||||||
const values = deps.map(dep => {
|
|
||||||
if (dep in changed) dirty = true;
|
|
||||||
return state[dep];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dirty) {
|
|
||||||
const newValue = fn.apply(null, values);
|
|
||||||
if (this._differs(newValue, value)) {
|
|
||||||
value = newValue;
|
|
||||||
changed[key] = true;
|
|
||||||
state[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this._computed[key] = c;
|
|
||||||
this._sortComputedProperties();
|
|
||||||
|
|
||||||
const state = assign({}, this._state);
|
|
||||||
const changed = {};
|
|
||||||
c.update(state, changed, true);
|
|
||||||
this._set(state, changed);
|
|
||||||
},
|
|
||||||
|
|
||||||
fire,
|
|
||||||
|
|
||||||
get,
|
|
||||||
|
|
||||||
on,
|
|
||||||
|
|
||||||
set(newState) {
|
|
||||||
const oldState = this._state;
|
|
||||||
const changed = this._changed = {};
|
|
||||||
let dirty = false;
|
|
||||||
|
|
||||||
for (const key in newState) {
|
|
||||||
if (this._computed[key]) throw new Error(`'${key}' is a read-only computed property`);
|
|
||||||
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
|
|
||||||
}
|
|
||||||
if (!dirty) return;
|
|
||||||
|
|
||||||
this._set(newState, changed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export { Store };
|
|
Loading…
Reference in new issue